Ben Brandt
Ben Brandt

Reputation: 2921

Automapper - Convert string property to SelectList?

I'm just starting to learn AutoMapper in an MVC project. I have a base entity "Attendee" with a string field for Gender (possible values of "M" or "F").

I already have a basic mapping created between my Attendee and my AttendeeEditView objects. What I want to do is convert the "M" or "F" Gender string on the model side to a SelectList on the ViewModel side, with the appropriate value selected in the list.

I think I need a ValueResolver to do this... here's what I've written:

public class GenderMenuResolver : ValueResolver<Attendee, SelectList> {
    protected override SelectList ResolveCore( Attendee source ) {
        List<object> items = new List<object>(){
            new{ Value = "F" , Text = "Female" },
            new{ Value = "M" , Text = "Male" }
        };

        string Gender = source.Gender ?? "";
        string selectedValue = new List<string>() { "M", "F" }.Contains( Gender.ToUpper() ) ? Gender.ToUpper() : "";

        SelectList GenderMenu = new SelectList(
            items,
            "Value",
            "Text",
            selectedValue
        );

        return GenderMenu;
    }
}

And my mapping code:

Mapper.CreateMap<Attendee, AttendeeEditView>()
.ForMember( dest => dest.Gender, opt => opt.ResolveUsing<GenderMenuResolver>() );


List<AttendeeEditView> ViewModel = Mapper.Map<List<AttendeeEditView>>( Attendees );

stepping through I can see this code executes and outputs a proper selectlist. However, I get the following error:

Mapping types: SelectList -> SelectList System.Web.Mvc.SelectList -> System.Web.Mvc.SelectList

Destination path: List`1[0].Gender.Gender

Source value: System.Web.Mvc.SelectList

First, the ".Gender.Gender" mapping seems incorrect.

But what appears to the root issue... an inner exception message reveals this:

"Type 'System.Web.Mvc.SelectList' does not have a default constructor"

Can anyone help me identify what I'm doing wrong, or perhaps a better approach I should be using? Thanks.

Upvotes: 2

Views: 2165

Answers (1)

Chris Pratt
Chris Pratt

Reputation: 239440

I think you're making this more difficult than it needs to be. Not everything needs to be mapped, in fact things like SelectLists almost certainly shouldn't be mapped because they're only relevant to a view model, not a model.

So, in your view model just do something like:

public string Gender { get; set; }

public SelectList GenderChoices
{
    get
    {
        return new SelectList(new List<SelectListItem>
            {
                new SelectListItem { Value = "M", Text = "Male" },
                new SelectListItem { Value = "F", Text = "Female" }
            }, "Value", "Text", Gender);
    }
 }

Where Gender would be mapped, but GenderChoices would just exist on your view model.

Then, in your view:

@Html.DropDownListFor(m => m.Gender, Model.GenderChoices)

Upvotes: 12

Related Questions