AutoMapper between Model and ViewModel with multiple properties - c#

Trying to map between a viewmodel and my model. In this scenario, i am getting taking data from a web service (creating a strongly typed view) and then loading it into a form. I then verify the client data from the web service, submit the form. It will do an insert or update depending on whether or not there's a record in my database.
I have been meaning to use AutoMapper for some time so this is my first experience with it. I want the properties from SearchResult to be mapped to my Client Model.
namespace Portal.ViewModels
{
public class ClientSearch
{
public SearchForm searchForm { get; set; }
public SearchResult searchResult { get; set; }
}
public class SearchForm
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string DOB { get; set; }
public string AccNumber { get; set; }
}
public class SearchResult
{
public int ClientID { get; set; }
public string AccNumber { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string Phone { get; set; }
public string City { get; set; }
public string Province { get; set; }
public string PostalCode { get; set; }
public string Country { get; set; }
public string Gender { get; set; }
public string DOB { get; set; }
public int Age { get; set; }
}
}
namespace Portal.Models
{
public class Client
{
public int ClientID { get; set; }
public string AccNumber { get; set; }
[Display(Name = "Last Name")]
public string LastName { get; set; }
[Display(Name = "First Name")]
public string FirstName { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string Phone { get; set; }
public string City { get; set; }
public string Province { get; set; }
public string PostalCode { get; set; }
public string Country { get; set; }
public string Gender { get; set; }
[Display(Name = "Date of Birth")]
public DateTime DOB { get; set; }
public int Age { get; set; }
}
}
In my controller below, i'm trying to use AutoMapper to map the data in clientSearch to my Client model based on an HttpPost.
However, I'm getting the error: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement when trying to create the Map. This is my attempt at using AutoMapper.
[HttpPost]
public ActionResult Process(ClientSearch clientSearch)
{
// Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement
Mapper.CreateMap<ClientSearch, Client>;
Client client = Mapper.Map<ClientSearch, Client>(clientSearch);
ClientRepository.InsertOrUpdate(client);
ClientRepository.Save();
}

You seem to be missing your '()' after:
Mapper.CreateMap<ClientSearch, Client>;
i.e. it should be:
Mapper.CreateMap<ClientSearch, Client>();

Related

Elastic search Nest (.Net) Total and Documents don't match

I'm having the following situation: the Total from the Valid Nest Response is equals 2 and the Documents count equal 0. I'm not sure how that is possible.
Found the solution. The problem was in my model. You see, my model was something like that:
public class Customer
{
public string Id { get; set; }
public string Name { get; set; }
public string Nickname { get; set; }
public string PersonType { get; set; }
public string Gender { get; set; }
public string MaritalStatus { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{dd/MM/yyyy HH:mm:ss}")]
public DateTime? BirthDate { get; set; }
}
And this Index had Documents missing some fields, like:
public class Customer
{
public string Id { get; set; }
public string Name { get; set; }
public string PersonType { get; set; }
public string Gender { get; set; }
}
The solution was adding the decorator PropertyName from Nest, to Map my model, like this:
public class Customer
{
[PropertyName("id")]
public string Id { get; set; }
[PropertyName("name")]
public string Name { get; set; }
[PropertyName("nickname")]
public string Nickname { get; set; }
[PropertyName("personType")]
public string PersonType { get; set; }
[PropertyName("gender")]
public string Gender { get; set; }
[PropertyName("maritalStatus")]
public string MaritalStatus { get; set; }
[PropertyName("birthDate")]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{dd/MM/yyyy HH:mm:ss}")]
public DateTime? BirthDate { get; set; }
}
Now it works!

Entity Framework - Update action and Automapper

For example, I have the following infrastructure class:
[Table("GeoHistory")]
public partial class GeoHistory
{
public int Id { get; set; }
public int CompanyId { get; set; }
public int DriverId { get; set; }
[StringLength(50)]
public string Name { get; set; }
public string Description { get; set; }
[StringLength(100)]
public string GeofenceLocation { get; set; }
[StringLength(100)]
public string GeofencePrevious { get; set; }
[StringLength(20)]
public string StateLocation { get; set; }
[StringLength(20)]
public string StatePrevious { get; set; }
public DateTime? DateTime { get; set; }
[StringLength(5)]
public string Heading { get; set; }
public decimal? Speed { get; set; }
[StringLength(50)]
public string Status { get; set; }
}
and the following View class (let's forget about domain layer):
public class GeoHistoryViewModel
{
public int Id { get; set; }
public int? CompanyId { get; set; }
public int? DriverId { get; set; }
[StringLength(50)]
public string Name { get; set; }
public string Description { get; set; }
}
as we can see, we edit only part of field list.
Now, we want to update data in DB. Of course, we can write like:
Infrastructure.Main.GeoHistory geoHistory = db.GeoHistories.Find(id);
geoHistory.CompanyId = model.CompanyId;
geoHistory.DriverId = model.DriverId;
geoHistory.Name = model.Name;
........
db.SaveChanges();
It works. But I want to use Automapper. And if I try to do the following:
Infrastructure.Main.GeoHistory geoHistory = mapper.Map<Infrastructure.Main.GeoHistory>(model);
db.GeoHistories.Attach(geoHistory);
db.Entry(geoHistory).State = EntityState.Modified;
db.SaveChanges();
It works, but of course remove values of fields, which are not exist in View Model, but exist in infrastructure class. How to use automapper, but don't lost these fields?

Best practices creating data models with same properties

New to MVC and looking for best practice when multiple models have the same properties. For example I have several models that have the address fields (address, city, state and zipcode). Let's say I have a customer model and supplier model with these fields. What is the best way to create the model? First example I started with has:
public class Customer
{
public int Id { get; set; }
public string AccountNumber { get; set; }
public string Customer { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; }
public string MainPhone { get; set; }
public string fax { get; set; }
public string ContactPhone { get; set; }
}
public class Supplier
{
public int Id { get; set; }
public string AccountNumber { get; set; }
public string Supplier { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; }
public string MainPhone { get; set; }
public string fax { get; set; }
public string ContactPhone { get; set; }
}
or alternately:
public class Customer
{
public int Id { get; set; }
public string AccountNumber { get; set; }
public string Customer { get; set; }
public Address CustomerAddress { get; set; }
public Phone MainPhone { get; set; }
public Phone fax { get; set; }
public Phone ContactPhone { get; set; }
}
public class Supplier
{
public int Id { get; set; }
public string AccountNumber { get; set; }
public string Supplier { get; set; }
public Address SupplierAddress { get; set; }
public Phone MainPhone { get; set; }
public Phone fax { get; set; }
public Phone ContactPhone { get; set; }
}
public class Address
{
public string AddressLine1 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; }
}
public class Phone
{
public int AreaCode { get; set; }
public int NPA { get; set; }
public int Station { get; set; }
}
Any suggestions on what is considered best practice is very much appreciated
I don't know that this is any different for MVC than for anything else, but IMO, the second is far better. When you decide to add a work address and home address, just like you already have a few phone numbers, you won't have to come up with even more contrived names to differentiate. All the standard reasons for reusable code would still apply.

How to setup a relational data model?

I am completely new to ASP.NET and was trying to cross-reference two different models with each other. I have 'Customer':
public class Customer
{
public int CustomerID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address { get; set; }
public string Zipcode { get; set; }
public string City { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
}
and 'Reservation':
public class Reservation
{
public int ReservationID { get; set; }
public string PetName { get; set; }
public DateTime Birthdate { get; set; }
public string Specie { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public Customer Customer { get; set; }
}
Now, each Reservation should belong to a Customer (as you can see in the bottom line of the Reservation model) and should therefore contain the CustomerID. On the other hand should each Customer contain references to each Reservation that was made by him.
How can I setup this relation?
Use an ICollection for a one to many relationship.
public class Customer
{
public int CustomerID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address { get; set; }
public string Zipcode { get; set; }
public string City { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public ICollection<Reservation> Reservations { get; set; }
}
Note I originally suggested a generic list, but there's a few subtle differences.

Instantiate one class variable with another

I have a the following classes
namespace MyClass.Models
{
public class Address : IIdentity
{
public string id { get; set; }
public DateTime updatedAt { get; set; }
public string user_id { get; set; }
public int building_number { get; set; }
public string street { get; set; }
public string area { get; set; }
public string county { get; set; }
public string country { get; set; }
public string postcode { get; set; }
public bool iscustomer { get; set; }
public bool islive { get; set; }
public string customer_id { get; set; }
public string store_id { get; set; }
public string phone_id { get; set; }
}
}
and
namespace MyClass.Models
{
public class User : IIdentity
{
public string id { get; set; }
public DateTime updatedAt { get; set; }
public string username { get; set; }
public string password { get; set; }
public bool isrestricted { get; set; }
public bool isbanned { get; set; }
public DateTime renewaldate { get; set; }
public string address_id { get; set; }
public string userlevel { get; set; }
}
}
What I am trying to do is create some test data to propagate through to my database so I can test my MVC5 website.
I am attempting to perform a look up on my instance of User within the Address class like so
user_id = context.User.FirstOrDefault(t=>t.address_id == id)
where id points to the id within the class I and trying instantiate.
VS2013 is saying that id does not exist in the current context which makes sense. Is there a way to do what I'm trying to achieve or am I better off setting the my _id from within the class itself and will that be okay when I run update-database from within the package manager console?
For example, the address class would become
namespace MyClass.Models
{
public class Address : IIdentity
{
public string id { get; set; }
public DateTime updatedAt { get; set; }
public string user_id { get {user_id = Users.FirstOrDefault(t=>t.address_id == id).id; } }
public int building_number { get; set; }
public string street { get; set; }
public string area { get; set; }
public string county { get; set; }
public string country { get; set; }
public string postcode { get; set; }
public bool iscustomer { get; set; }
public bool islive { get; set; }
public string customer_id { get {customer_id = Customers...;} }
public string store_id { get {store_id = Stores...;} }
public string phone_id { get {phone_id = Phones...;} }
}
}

Categories