1

I have a view, that is of Inherits from System.Web.Mvc.ViewPage<P>.

Type P has a property of Type C, ie, P could be:

class P
{
   public string Name { get; set; }
   public C OtherData { get; set; }
}

The View in question is for creating a new P, and as such I want to create a DropDown list of all the available C's.

So the dropdown could be:

  • C1
  • C2
  • C3
  • C4

I've tried creating the List<SelectListItem> object for the C's in my controller and then pass them to the view using ViewData but this does not work, as when I try to submit I get the exception:

System.InvalidOperationException: There is no ViewData item of type 'IEnumerable<SelectListItem>' that has the key C.

So my question is, how do I create a list of C objects to display in my View that inherits from type P. The list of objects is pulled from a database and as such I cannot just simply hardcode the options into the view.

Do I need to create another Model type that marries the 2 types together?

2 Answers 2

1

The way I do this is as follows:

ViewModel:

public class ViewModel
{
    public string Name { get; set; }
    public List<SelectListItem> ListOfCs { get; set; }
}

My View has the following:

<%:Html.EditorFor(model => model, new { ListOfCs = Model.ListOfCs })%>

I use the default Object.ascx outlined in Brad Wilson's excellent series of blog posts on ASP.NET MVC 2 Templates

Then I add a dropdown template for that dropdown in the Views/Shared/EditorTemplates folder and call it something like CClassDropDown:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<string>" %>

<%: Html.DropDownList(null, new List<SelectListItem>(ViewData["ListOfCs"] as List<SelectListItem>), "Select C...")%>

And then I add a partial metadata class for the P object:

[MetadataType(typeof(PMetaData))]
public partial class P
{
    public class PMetaData
    {
        [UIHint("CClassDropDown")] 
        [DataType(DataType.Text)]
        public object C { get; set; }

    }
}

to the metadata for that class property so it knows to use the template I specified.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks morgan, Where do I add this metadata class? Never seen that before!
@AndyC - you would create a partial class for the containing object (P). You can find a great explanation of how to use it in the MVC Music Store tutorial: mvcmusicstore.codeplex.com. Look for "Using MetaData Partial Classes with Entity Framework". And incidentally, between that tutorial and Brad Wilson's templating series, I learned everything I need to know about MVC and EF4 (mostly!)
@AndyC as for where specifically to put the partial classes, I put them in the Model folder and I call them out with a .metadata.cs filename, so in this case: P.metadata.cs. Note that they are partial classes to the default EF4 generated classes - I don't usually do metadata partial classes on the viewmodel, although I did for your example.
@Morganpdx I assume this solution is still valid if I'm using Linq to Sql instead of EF? :)
@Andy - yes, it should work the same. The key point is the UIHint on the partial metadata class; that can be added to any class, not just an EF-generated one. You'll need to have the System.ComponentModel.DataAnnotations in your partial class for it to work.
0

I've only done this with Linq2Sql so YMMW.

In Linq2Sql the entity has both an foreign entity, and a foreign entity key.

So, it would have both C and C_id.

class P
{
public string Name { get; set; }
public C OtherData { get; set; }
public int OtherData_id { get; set; }
}

In that case its just a case of doing

MyViewData {
  SelectList CList = new SelectList( ctx.getCs(), "C_id", "C_name")
}  

and in the page doing

<%= Html.DropDownList("OtherData_id", Model.CList,"-") %>

In this way

TryModelUpdate(...) 

will correctly set the OtherData_id, which in turn will cause OtherData to be resolved when accessed.

Comments

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.