Can AutoMapper map object to model property of the same type - asp.net-mvc-3

I am attempting to improve my data flow between my MVC 3 Model and Views (mainly CRUD). I have taken the approach of using ViewModels and FormModels. My ViewModel contains everything it need to represent the view FormData, DropDownLists etc. The FormModel simply contains the FormData fields that are submitted by the form and are needed to update a record.
My question is can I use AutoMapper to map UserDto information onto my FormData field in my ViewModel?
Obviously my mapping below is only mapping between the two object and not an object to property but I have tried using the ‘.ForMember’ mapping options but they are again for object members not an object to an object member. I have also looked at Custom Type Convertors but not sure if this is the right way to go.
Mapper.CreateMap<UserDto, UserViewModel>();
Mapper.CreateMap<UserViewModel, UserDto>();
public class UserViewModel
{
public User FormData { get; set; }
// DropDownLists
// Other view specific data
}
public class UserFormModel
{
public int UserId { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Age { get; set; }
[Required]
public string Email { get; set; }
}
Any help would be much appreciated.

You need to create the map to the FormData property type and then tell AutoMapper to use this map.
(The following will likely not compile; I'm in the process of recreating my work machine and am working from memory).
Mapper.CreateMap<UserDto, User>(); // set up property mapping
Mapper.CreateMap<UserDto, UserViewModel>()
.ForMember(vm => vm.FormData, map => map.MapFrom(dto => Mapper.Map<UserDto, User>(dto)));

Related

RequiredAttribute doesn't appear on client-side validation, on derived class

My viewmodel inherits from a class that inherits from an abstract class that has a property with a [Required] attribute, but the rule doesn't appear in the DOM and unobtrusive validation doesn't catch the error.
The display attribute goes through fine, but the validation DOM attributes are not added to the textarea
my view has this:
#model FormPersonView
....
#Html.TextAreaFor(m => m.Description)
#Html.ValidationMessageFor(m => m.Description)
my code has this:
public class FormPersonView : Person
{
//View related stuff
.....
.....
}
public class Person : BasePerson
{
//Person related stuff - validation for these work!
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
}
public abstract class BasePerson
{
//Base person stuff - validation for this doesn't work!
public string Id { get; set; }
[Required]
[Display("Short description of the person")]
public string Description { get; set; }
}
Why does it work with one level of inheritance but not two? It does work on the server side.
Had exactly this problem. While defining the view, the model comes as a type you defined #model FormPersonView. Data annotations will only work on that specific type, even if you have derived properties from children, their data annotations won't be engaged.
The solution that I came up with in my project was to define editor templates for types I needed data annotations to work properly and then calling #EditorFor on those models. Then and only then were data annotations operating as expected.
Hope this help you.

How to make single controller for two database classes - MVC3

I have two database classes as defined below:
public class TopDate
{
[Key]
public int DateId { get; set; }
public DateTime Date { get; set; }
}
public class TopSong
{
[Key]
public int SongId { get; set; }
public string Title { get; set; }
public int DateId { get; set; }
}
where DateId is foreign key to TopSong
I am creating a controller through which i can create, delete or edit these database values.
When i right click on controller class and add controller i can only select one of the two classes defined above. Is there a way to make 1 controller to handle database updates to both these tables on one page?
Error Image:
Your controller should not be dealing directly with domain objects (meaning those things that are directly associated with your database). Create a ViewModel that contains the properties that you need, use your service layer to populate the ViewModel and your controller will use that as the Model for its base. An example of your ViewModel could be something like the following given your description above:
public class MusicViewModel
{
public int SongId {get;set;}
public string Title {get;set;}
public IEnumerable<DateTime> TopDates {get;set;}
}
This view model would contain a list of all dates that a specific song was a Top Song.
The objects you showing (code) are database classes (so called domain objects).
What you need to do is to define a view model, a standard ASP MVC practice:
you define a class, that is tailored for specific view and only containing data relevant to that particular view. So you will have a view model for a view that will create a song, another that will update it etc.
Actually situation you describing is classical situation to use view models. Using domain objects in the views, however, is really really bad practice and prone to more problems than you want to deal with.
Hope this helps.

Ignoring properties when serializing

I'm pulling my hair out on this one.
I am trying to implement a multi-step wizard, and i'm using the Html.Serialize html helper in MVC3 Futures. This works well, except one of the properties in my model is a SelectList. I don't want this property serialized (and it blows up when it tries anyways).
I can't use [NonSerialized] because that only works on fields, not properties. I've even tried some of the other normal ways such as [XmlIgnore] (which I didn't think would work anyways).
Can anyone suggest an attribute that will ignore a property in a model when using Html.Serialize?
EDIT:
The error I get when I try to serialize is a InvalidDataContractException. There is this message:
Type 'System.Web.Mvc.SelectList' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute. If the type is a collection, consider marking it with the CollectionDataContractAttribute. See the Microsoft .NET Framework documentation for other supported types.
However, if I do this then I have to mark all the members with [DataMember] just to exclude 1 property, which seems kind of stupid.
UPDATE:
A quick example of this is this bit of code (make sure to add reference to System.Runtime.Serialization.dll):
Test.cs
[Serializable]
public class Test
{
public int ID { get; set; }
[IgnoreDataMember]
public SelectList TestList { get; set; }
}
HomeController.cs
public ActionResult About()
{
return View(new Test() { ID = 0, TestList = new SelectList(new [] {""})});
}
Home/About.cshtml
#using Microsoft.Web.Mvc
#model MvcApplication3.Models.Test
#Html.Serialize("Test", Model)
This generates the InvalidDataContractException
public class MyViewModel
{
[IgnoreDataMember]
public SelectList Items { get; set; }
...
}
or simply:
public class MyViewModel
{
public IEnumerable<SelectListItem> Items { get; set; }
...
}

In ASP.NET MVC3 how do you stay DRY with very similar but slightly different viewmodels?

In building an app, we created a generic object model to store some values, the viewmodel looks a bit like this at the moment:
public class FooViewModel {
public int ID { get; set; }
public byte FooType { get; set; }
[Required]
[Display(Name = "Bar Name")]
public string Name { get; set; }
[Required]
public string Email { get; set; }
//etc, etc
}
The problem is: depending on the FooType, we want to have the Display Name to be different and the Email is not required for type 1 and 2, but is required for type 3 and 4.
We tried seperating out the properties that differ per type in to classes that inherit from this one, but the validation does a fallback on what is specified in the base type, so that didn't work.
Currently, the only option seems to be to create a viewmodel for each FooType (and also seperate controllers and view), which leads to a lot of code duplication.
What are other ways to keep this DRY?
To benefit a validation context (e.g. validating objects in different contexts), I strongly recommend using FluentValidation library.
You could implement a custom RequiredIf validation attribute, or you could implement IValidatableObject.

MVC 3: Use a VERY custom format for a Date with automapping on server-side

I have a very confusing problem, and I am able to solve it, but there has to be a Out-Of-The-Box-Solution.
The situation is as following:
An user inputs on the client-side a date (i.e. with a date-picker) which outputs the following value to the textbox:
Mi 22.02.2012 (KW 8)
I have a Button which posts my form with this textbox to an controller-action.
Let's say you have the following controller action which takes a MyType as Parameter
[HttpPost]
public ActionResult Create(MyType model)
{
//model.Date is always null
//(or in case the DateTime is not Nullable<T>, the value is DateTime.Min
}
public class MyType
{
public DateTime? Date { get; set; }
}
The question is simple:
How do I map the input to the DateTime?
I do not want to add properties to my class like in the following example:
public class IDontWantThis
{
public DateTime? Date { get { /* Some custom string parsing with DateText */ } }
public string DateText { get; set; } //this would be the auto-mapped property
}
How a date is displayed in the view is of no concern to the controller.
I would add a hidden field with the name of the property you want the datetime to map on the viewmodel (Date). On the client, using javascript, you can format this date any way you want, as long as the hidden field contains the datetime you need to work with.
So let the datepicker store the selected date twice, once with your weird date formatting for display and another time in a hidden field in a common format the modelbinder will understand.
This is what ViewModels are for. I understand that you don't want your domain Model to include a DateText member, but you really should consider something like this:
public class MyType
{
public DateTime? Date { get; set; }
}
public class MyTypeViewModel
{
public MyType MyType { get; set; }
public string DateText { get; set; }
}
What your requirement is one of the main points that makes ViewModels so powerful. Using an intermediate class between your View and your Model to link them together. This way, you won't have any trace of "formatting" data in your Model (MyType).

Resources