views:

46

answers:

1

I am receiving this error:

The ViewData item that has the key 'DepartmentId' is of type 'System.Int32' but must be of type 'IEnumerable'.

with the following set up. I am not sure how to resolve it. The error is happening in the Model View code. This line: public void MapTo(Person domainModel). I am using AutoMapper to map ViewModel back to DomainModel (reversing the initial mapping of DomainModel to ViewModel).

Domain model (using LINQ to SQL, so this is a partial class):

public partial class Person { }

// Validation rules
public class Person_Validation
{
    [HiddenInput(DisplayValue = false)]
    [ScaffoldColumn(false)]
    public object PersonId { get; set; }

    [HiddenInput(DisplayValue = false)]
    [ScaffoldColumn(false)]
    public object DepartmentId { get; set; }

    [DisplayName("Employee Name")]
    [Required(ErrorMessage = "Employee Name is required")]
    [StringLength(50, ErrorMessage = "Employee Name cannot be more than 50 characters")]
    public object Name { get; set; }

    [HiddenInput(DisplayValue = false)]        
    public object Active { get; set; }

    [HiddenInput(DisplayValue = false)]
    public object DateAdded { get; set; }

    [HiddenInput(DisplayValue = false)]
    public object DateDeleted { get; set; }

    public object Department { get; set; }     
}

This is my Model View:

public class PersonViewModel
{       
    public object PersonId { get; set; }

    public object DepartmentId { get; set; }

    public object Name { get; set; }

    public object Active { get; set; }

    public object DateAdded { get; set; }

    public object DateDeleted { get; set; }    

    public object DepartmentName { get; set; }

    //helper method
    public void MapTo(Person domainModel)
    {
        Mapper.Map(this, domainModel);
    }
}

Controller Class Code:

[HttpPost]        
public ActionResult Edit(PersonViewModel viewModel)
{
    var domainModel = new Person();                                       
    try                    
    {                      
        viewModel.MapTo(domainModel);
        UpdateModel(domainModel);
        _personRepository.Save();
        return RedirectToAction("Index", "Person");
    }                      
    catch                  
    {                      
        return View(viewModel);
    }                      
} 

And my View HTML code:

<div class="editor-field">                
<%: Html.DropDownList("DepartmentId", (IEnumerable<SelectListItem>)ViewData["DepartmentList"])%>                                     
<%: Html.ValidationMessageFor(model => model.DepartmentId) %>
</div>
+1  A: 

you're not really following the best practices of developing a mvc application.

About the error: the Html.DropDownList looks for Data of type IEnumerable<SelectListItem> in the model but it finds an int instead (DepartmentId)

your ViewModel should not have the MapTo method, it breaks the single responsibility principle

in your action method you don't do any server side validation like:

if(!ModelState.IsValid)
{
   //rebuild the viewmodel and return the view
}

catching everything in the action is also not necessary (and bad) you do this in Global.asax Application_Error instead

attributes like HiddenInput, ScaffoldColumn, Validation and anything else UI related should be on you ViewModel not in your domain model


for a good sample of using viewmodels & validation & mapping between entity <-> viewmodel I recommend you to look at the Samples solution from here

I did this sample and it's main purpose is to demonstrate the usage of ValueInjecter (mapping technology)

Omu