I have working solution, but a bit doubt if I made it correctly. I have base class from which derive 3 other classes Ad:
public class Ad
{
public int Id { get; set; }
public string Title { get; set; }
public Address Address { get; set; }
}
My Address class look like this:
public class Address
{
[ForeignKey("Ad")]
public int AddressId { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string ZipCode { get; set; }
public virtual Ad Ad { get; set; }
}
Now I'm using automapper with this mapping:
Mapper.Initialize(config =>
{
config.CreateMap<Auto, AutoViewModel>()
.ForMember(m => m.City, vm => vm.MapFrom(m => m.Address.City))
.ForMember(m => m.Street, vm => vm.MapFrom(m => m.Address.Street))
.ForMember(m => m.ZipCode, vm => vm.MapFrom(m => m.Address.ZipCode)).ReverseMap();
});
Where AutoViewModel looks like this:
public class AutoViewModel
{
public int Id { get; set; }
public string Title { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string ZipCode { get; set; }
}
In my Create and Edit actions I use this binding:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, AutoViewModel vm)
{
Address address = new Address();
address.AddressId = vm.Id;
address.City = vm.City;
address.Street = vm.Street;
address.ZipCode = vm.ZipCode;
var auto = Mapper.Map<Auto>(vm);
auto.Address = address;
if (id != auto.Id)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(auto);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!AutoExists(auto.Id))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction("Index");
}
return View(auto);
}
Is this way correct? Is there elegant way to do it? I had to specify AddressId explicit because otherwise I'm getting duplicate Foreign key error message...
Related
Entity:
public class AccountEntity: MasterEntity
{
public AccountType AccountType { get; set; }
public DepartmentEntity Department { get; set; }
public string LeadSource { get; set; }
public ResourceEntity AccountManager { get; set; }
public AccountQualificationStatus QualificationStatus { get; set; }
}
public class DepartmentEntity : MasterEntity
{
}
public class ResourceEntity : MasterEntity
{
public string Email { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
}
public abstract class MasterEntity: Entity
{
public string Name { get; set; }
public string Code { get; set; }
}
Model
public class Accounts
{
private string depname;
public int Id { get; set; }
public string Name { get; set; }
public int Code { get; set; }
public string AccountType { get; set; }
public string Department { get; set; }
}
public AccountMappingProfile()
{
CreateMap<Account, AccountTest>().ReverseMap();
CreateMap<Opportunity, OpportunityEntity>().ReverseMap();
CreateMap<Accounts, AccountEntity>().ReverseMap();
CreateMap<Resource, ResourceEntity>().ReverseMap();
CreateMap<Projects, ProjectEntity>().ReverseMap();
}
public static class AccountMapper
{
private static readonly Lazy<IMapper> Lazy = new Lazy<IMapper>(() =>
{
var config = new MapperConfiguration(cfg => {
cfg.ShouldMapProperty = p => p.GetMethod.IsPublic || p.GetMethod.IsAssembly;
cfg.AddProfile<AccountMappingProfile>();
});
var mapper = config.CreateMapper();
return mapper;
});
public static IMapper Mapper => Lazy.Value;
}
I am able to fetch resource details .while I am fetching accounts with department and resources, the value for department is giving me null after automapping.
public async Task<IEnumerable<Accounts>> GetAccounts()
{
try
{
var accounts = await _context.Account.Include(c=>c.Director).ToListAsync();
// accounts = await _context.Account.Include(c => c.Department).ToListAsync();
return AccountMapper.Mapper.Map<List<Accounts>>(accounts);
}
}
controller method:
public async Task<IEnumerable<Accounts>> GetClients()
{
var result = await _repository.GetAccounts();
return result;
}
if I am uncommenting the code to include department, its is giving the object name.
I need to get the department details as well. how can i get that.Department entity is inheriting master entity.
I'm working on an web API, where it needs to receive the multi-part form data with in a model. As of now it's not receiving the request and showing the Bad request When I tried from the Postman.
My model :
public class InvoiceDetails
{
public int? po_id { get; set; }
public DateTime created_date { get; set; }
public string grn_status { get; set; }
public int utilization_amount { get; set; }
public int currency_id { get; set; }
public string currency_code { get; set; }
public string currency_symbol { get; set; }
[FromForm(Name = "invoice_file")]
public List<IFormCollection> invoice_file { get;set;}
[FromForm(Name = "other_files")]
public List<IFormCollection> other_files { get; set; }
}
In the above class/model "invoice_file" and "other_files" can have multiple file uploads so I made it List.
My Action Method :
[HttpPost]
[Route("CreateInvoice")]
public IActionResult CreateInvoice([FromForm]InvoiceDetails idobj )
{
//var modelData = Request.Form["invoice_file"];
Response resobj = new Response();
try
{
if (idobj.invoice_file.Count > 0)
{
resobj = _dataContext.AddInvoice(idobj);
if (resobj.flag == true)
{
Upload(idobj);
}
}
else
{
resobj.flag = false;
resobj.message = "please upload atleast one invioce file";
}
}
catch (Exception ex)
{
}
return Ok(resobj);
}
How can I make the action method or model, in such a way that user can upload the model with multiple files to the properties other_files & invoice_file.
Reference of postman Image
As CodeCaster says,add Content-Type:multipart/form-data; and change List<IFormCollection> to List<IFormFile>.It is not changing the whole model to List.So you can also retrieve other information which exists in your model with idobj.xxx.Change
public class InvoiceDetails
{
public int? po_id { get; set; }
public DateTime created_date { get; set; }
public string grn_status { get; set; }
public int utilization_amount { get; set; }
public int currency_id { get; set; }
public string currency_code { get; set; }
public string currency_symbol { get; set; }
[FromForm(Name = "invoice_file")]
public List<IFormCollection> invoice_file { get;set;}
[FromForm(Name = "other_files")]
public List<IFormCollection> other_files { get; set; }
}
to
public class InvoiceDetails
{
public int? po_id { get; set; }
public DateTime created_date { get; set; }
public string grn_status { get; set; }
public int utilization_amount { get; set; }
public int currency_id { get; set; }
public string currency_code { get; set; }
public string currency_symbol { get; set; }
[FromForm(Name = "invoice_file")]
public List<IFormFile> invoice_file { get; set; }
[FromForm(Name = "other_files")]
public List<IFormFile> other_files { get; set; }
}
result:
IFormCollection is used to retrieve all the values from posted form data.refer to the official document.
If you want to use c,you can try to use it,you can do like this
public IActionResult CreateInvoice([FromForm]IFormCollection idobj)
and you need to get the data you want to foreach keys of IFormCollection,so public List<IFormCollection> invoice_file { get;set;} is better than use IFormCollection.
I have a model Template with List<Symbol> symbols, and an equivalent ViewModel TemplateJS with List<SymbolJS>. When I query for a Template, ProjectTo<TemplateJS> seems to throw an Exception and I'm not sure why.
Exception: "Argument types do not match"
I would also like to Include Symbol in my query but I'm not exactly sure how to map that object as well. Would this need be done in a separate query?
Any help is appreciated! Thanks!
Models :
public class Template
{
public int Id { get; set; }
public string Name { get; set; }
public List<Exercise> Exercises { get; set; }
public List<Symbol> Symbols { get; set; }
}
public class Symbol
{
public int Id { get; set; }
public int TemplateId { get; set; }
public Template Template { get; set; }
public char Letter { get; set; }
public string ImgSource { get; set; }
}
public class TemplateJS
{
public int Id { get; set; }
public string Name { get; set; }
public List<SymbolJS> Symbols { get; set; }
}
public class SymbolJS
{
public char Letter { get; set; }
public string ImgSrc { get; set; }
}
AutoMapper :
CreateMap<Template, TemplateJS>()
.ReverseMap();
CreateMap<Symbol, SymbolJS>()
.ReverseMap();
Query :
public async Task<TemplateJS> GetTemplateAsync(int Id)
{
try
{
var q = await _dbContext.Template
// .Include(x => x.Symbols)
.Where(x => x.Id == Id)
.ProjectTo<TemplateJS>(_mapper.ConfigurationProvider)
.SingleOrDefaultAsync();
return q;
}
catch (Exception e)
{
throw e;
}
}
Recently I've experienced this error while trying to update entities in MS SQL Database.
I have two models:
[AutoMap(typeof(Employees))]
[Table("Employees")]
public class Employees : FullAuditedEntity
{
public Employees()
{
EmployeesAdresses = new HashSet<EmployeesAdresses>();
WorkTimeEntries = new HashSet<WorkTimeEntries>();
ContractEntries = new HashSet<ContractEntries>();
}
public string Name { get; set; }
public string Surname { get; set; }
public string Description { get; set; }
public bool IsActive { get; set; }
public ICollection<EmployeesAdresses> EmployeesAdresses { get; set; }
public ICollection<WorkTimeEntries> WorkTimeEntries { get; set; }
public ICollection<ContractEntries> ContractEntries { get; set; }
[NotMapped]
public List<GroupRelations> GroupRelations { get; set; }
}
[AutoMap(typeof(EmployeesAdresses))]
[Table("EmployeesAdresses")]
public class EmployeesAdresses : FullAuditedEntity
{
public string Street { get; set; }
public string HouseNumber { get; set; }
public string ApartmentNumber { get; set; }
public string PostalCode { get; set; }
public string City { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
public bool IsDefault { get; set; }
public bool IsActive { get; set; }
[ForeignKey("Employees")]
public int EmployeeId { get; set; }
public virtual Employees Employee { get; set; }
}
I am trying to update Employee Adress using simple appservice:
public async Task UpdateEmployee (Employees employeeInput)
{
try
{
var _employee = await _employeesRepository.GetAllIncluding(x => x.EmployeesAdresses).Where(x => x.Id == employeeInput.Id).SingleOrDefaultAsync();
if (_employee == null)
throw new Exception($"Brak pracownika o ID: {employeeInput.Id}");
_employee.EmployeesAdresses.Clear();
_employee.WorkTimeEntries.Clear();
ObjectMapper.Map(employeeInput, _employee);
await _employeesRepository.UpdateAsync(_employee);
}
catch (Exception ex)
{
throw new UserFriendlyException(#"Wystąpił błąd podczas aktualizacji pracownika.", ex.Message, ex.InnerException);
}
}
I am getting StackOverFlowException and I really don't know whats the issue. Last error on stacktrace in diagnostic tool event tab is StringCompare error.
Did you experience such a behaviour? Any ideas what might be a problem?
I am trying to use fluent validation in ServiceStack. I've added the validation plugin and registered my validator.
Plugins.Add(new ValidationFeature());
container.RegisterValidators(typeof(CreateLeaveValidator).Assembly);
I have implemented a validator class for my service model:
public class CreateLeaveValidator : AbstractValidator<CreateLeave>
{
public CreateLeaveValidator()
{
RuleFor(cl => cl.StudentId).NotEmpty();
RuleFor(cl => cl.LeaveDepart).NotEmpty().GreaterThan(DateTime.Now).WithMessage("Leave must begin AFTER current time and date.");
RuleFor(cl => cl.LeaveReturn).NotEmpty().GreaterThan(cl => cl.LeaveDepart).WithMessage("Leave must end AFTER it begins.");
RuleFor(cl => cl.ApprovalStatus).Must( status => ( ("P".Equals(status)) || ("C".Equals(status)) || ("A".Equals(status)) || ("D".Equals(status)) ) );
}
}
Service Model:
[Route("/leaves", "POST")]
public class CreateLeave : IReturn<LeaveResponse>, IUpdateApprovalStatus
{
public int StudentId { get; set; }
public DateTime RequestDate { get; set; }
public DateTime LeaveDepart { get; set; }
public DateTime LeaveReturn { get; set; }
public string Destination { get; set; }
public string HostRelationship { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Postal { get; set; }
public string Hostphone { get; set; }
public string Cellphone { get; set; }
public string Transport { get; set; }
public string Driver { get; set; }
public string Companions { get; set; }
public string Reason { get; set; }
public string ApprovalStatus { get; set; }
public DateTime ApprovalDate { get; set; }
public string ApprovalComment { get; set; }
public string ApprovalReason { get; set; }
public int ApprovalUser { get; set; }
}
But when I create a request with no StudentId or an invalid ApprovalStatus, the validator does not appear to fire and catch the invalid request.
How can I go about troubleshooting the cause of this?
UPDATE: Correction it appears validators are working with my actual service but not in my unit tests. I'm guessing I must not be configuring my apphost correctly in the unit test setup. Here's my test constructor:
public LeaveTests()
{
Licensing.RegisterLicense(#"[license key]");
appHost = new BasicAppHost(typeof(ApiServices).Assembly).Init();
ServiceStack.Text.JsConfig.DateHandler = ServiceStack.Text.DateHandler.ISO8601;
appHost.Plugins.Add(new ValidationFeature());
appHost.Container.RegisterValidators(typeof(CreateLeaveValidator).Assembly);
}
ServiceStack Validation filters are executed in a Global Request Filter which require a full integration test to run, e.g:
public class MyIntegrationTests
{
ServiceStackHost appHost;
public MyIntegrationTests()
{
appHost = new AppHost()
.Init()
.Start("http://localhost:8000/");
}
[OneTimeTearDown] void OneTimeTearDown() => appHost.Dispose();
[Test]
public void Execute_validation_filters()
{
var client = new JsonServiceClient("http://localhost:8000/");
try
{
var response = client.Post(new CreateLeave { ... });
}
catch(WebServiceException ex)
{
//...
}
}
}