8

Probably simple, but I seem to be missing something.

Two Models:

public class Hardware
{
    [Required]
    public int Id { get; set; }

    public int SerialNum { get; set; }
    public int ProductNum { get; set; }
    public string Notes { get; set; }
    public DateTime PurchaseDate { get; set; }
    public DateTime WarrantyExpiration { get; set; }

    public virtual Manufacturer Manufacturer { get; set; }
}

public class Manufacturer
{
    public int Id { get; set; }

    [Required]
    public string Name { get; set; }

    public virtual ICollection<Hardware> Hardware { get; set; }
}

When I go to the Hardware Create view, I want to to be able to select from a dropdown of Manufacturers, and when it submits it should establish a relationship between the piece of hardware and the select Manufacturer.

At the moment, I've been using the following to build a selectList in the controller

SelectList selectList = new SelectList(db.Manufacturers, "Id", "Name");
ViewBag.selectList = selectList;

And then casting it in the view:

@Html.DropDownListFor(model => model.Manufacturer, ViewBag.selectList as SelectList)\

However, it seems like there should be a better way to do this - perhaps creating a viewModel that inherits from Hardware with a SelectList typed property?

1
  • 1
    Having a View Model inherit from an Entity Framework entity would be a really bad idea. You should strive to completely isolate your views from your entities. It might be more work at first, but once you get the pattern down you will be really glad that you did. Commented Jan 22, 2013 at 21:51

1 Answer 1

17

As your application gets more and more complicated, you will see your MVC application turning into M-VM-V-C, VM is dedicated ViewModels that usually adds all the things that your UI layer need in order to generate the UI.

I personally wouldn't go with inheritance in this case, because your ViewModel is not a specialized version of your Model. It's just what your UI need to create a View (this is really up to you).

My ViewModel would look something like this:

public class HardwareVm
{
     public Hardware Hardware { get; set; }
     public IEnumerable<SelectListItem> Manufacturers { get; set; }
} 

in the View:

@Html.DropDownListFor(model => model.Hardware.Manufacturer,  Manufacturers)

controller:

var manufacturers = db.Manufacturers.Select(m => new SelectListItem {Text = m.Name, Value = m.Id });
var model = new HardwareVm { Manufacturers = manufacturers };
Sign up to request clarification or add additional context in comments.

6 Comments

Good advice, and it makes a lot of sense. Unfortunately, using a SelectList this way also produces a 'No parameterless constructor defined for this object' error. The relevant info I found was here: stackoverflow.com/a/7849504/451075 Unless of course I am using it wrong.
Hmm, now I'm at a loss as how to assign it in my controller. I was using: HardwareVm hardware = new HardwareVm { Manufacturers = new SelectList(db.Manufacturers, "Id", "Name" )}; to create my SelectList
Sadly, not. The initial issue is that Name can't be converted to Int type. However, even if you do get past that, you still wind up with a There is no ViewData item of type 'IEnumerable<SelectListItem>' that has the key 'Hardware.Manu' upon submission. I'm starting to think the ViewBag may not be so bad after all :D but I appreciate the help - the point about ViewModels is well-received. github.com/jelatin/inventoryTracker
@NickBrown in the application I am currently working on, I have this type of dropdown lists all over the place, the error you are getting make me think you are still using ViewData.Manufacturars instead on Model.Manufacturars
I ended up using SelectList selList = new SelectList(db.Manufacturers, "Id", "Name"); to build the list in the controller, as Value = m.Id threw an error about converting integers to strings and it did not like .ToString()
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.