views:

2612

answers:

1

Hi all

I am trying to learn MVC2, C# and Linq to Entities all in one project (yes, I am mad) and I am experiencing some problems with DropDownListFor and passing the SelectList to it.

This is the code in my controller:

        public ActionResult Create()
    {
        var Methods = te.Methods.Select(a => a);

        List<SelectListItem> MethodList = new List<SelectListItem>();

        foreach (Method me in Methods)
        { 
            SelectListItem sli=new SelectListItem();
            sli.Text = me.Description;
            sli.Value = me.method_id.ToString();
            MethodList.Add(sli);
        }


        ViewData["MethodList"] = MethodList.AsEnumerable();

        Talkback tb = new Talkback();
        return View(tb);
    } 

and I am having troubles trying to get the DropDownListFor to take the MethodList in ViewData. When I try:

<%:Html.DropDownListFor(model => model.method_id,new SelectList("MethodList","method_id","Description",Model.method_id)) %>

It errors out with the following message DataBinding: 'System.Char' does not contain a property with the name 'method_id'.

I know why this is, as it is taking MethodList as a string, but I can't figure out how to get it to take the SelectList. If I do the following with a normal DropDownList:

<%: Html.DropDownList("MethodList") %>

It is quite happy with this.

Can anyone help?

+1  A: 

EDIT: So you are using Entity Framework, yes? In that case with the addition info you put in the comments, you would want to do something like this:

public ActionResult Create()
{
    var viewModel = new CreateViewModel(); // Strongly Typed View

    using(Entities dataModel = new Entities()) // 'te' I assume is your data model
    {
         viewModel.Methods = dataModel.Methods.Select(x => new SelectListItem()
         {
              Text = x.Description,
              Value = x.method_id.ToString()
         });
    }

    return View(viewModel);
}

Your strongly typed view model would be:

public class CreateViewModel
{
     public string SelectedMethod { get; set; }
     public IEnumerable<SelectListItem> Methods { get; set; }
}

Your view code would be:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<CreateViewModel>" %>
 <%-- Note the Generic Type Argument to View Page! --%>
 <%: Html.DropDownListFor(m => m.SelectedMethod, Model.Methods) %>
Tejs
The Talkback class is an L2E table class. It contains a method_id which has a 0..1 relationship with the Methods table, therefore I only have method_id Scalar property from Talkback table and Method navigation property to the particular Method relating to that record's method_id.So I can get the method relating to a particular talkback record which, as this is a create action, would be null anyway. However, I can't get access to all methods through the talkback model.Hope that makes sense!
hermiod
Updated with additional code. Try this and see if that works for you!
Tejs
Now I get the error 'No overload for method 'DropDownListFor' takes 1 arguments'. Maybe I have misunderstood MVC but I thought that it would be possible to generates all the Views from the Database model itself and modify as necessary. I have seen some examples of passing arbitrary lists through to the view (via ViewData, which my original code was based off of), is there any way to make this work in my situation?Thanks for your help Tejs
hermiod
Oops, sorry. I got the method signature for DropDownListFor wrong. I've updated the code. You can generate from a class - when you select to add a view, select the checkbox for 'Strongly Typed View', and then, once you select a type, the second drop down in the Add View dialog should be enabled letting you auto generate HTML from that model.
Tejs
For example, here is a screenshot: http://img576.imageshack.us/img576/5541/sampleviewdialog.png
Tejs
Thanks Tejs, that worked fine.I generated my original Create view from the talkback class, but is there a way to get around the problem which resulted in my problem above, whereby the talkback class doesn't have access to all possible methods, just the one it has.This is why i was using ViewData as several website indicated that this was a good way to go, dunno why i couldn't get it work.
hermiod
Made the mistake of posting before running! When running I get the following error on the DropDownListFor line of code:The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.I have checked in the code and nowhere am I calling dispose.
hermiod
Ah, that's a funny thing about entity framework. Just call .ToList() on the end of the .Select() and that should disappear. That debug means that you didn't enumerate the collection before trying to use it (and by the time it gets to the view, the ObjectContext is out of scope). The L2E is lazy evaluated - call an aggregator like .ToList() to fully enumerate the collection.
Tejs
Thanks for all your help Tejs. I've found a way that seemns to work how I want. I have recreated the Create View to run directly from the Talkback class in my L2E model. I've taken a combination of 2 solutions located at http://forums.asp.net/p/1544661/3773019.aspx and http://stackoverflow.com/questions/1066760/problem-with-converting-int-to-string-in-linq-to-entities. The only reason I've decided not to use your solution is because I really want to keep the views working from my database models rather than intermediate classes. Will flag you as answer as you did provide a very good solution
hermiod
I'm starting to think that L2E isn't really worth it for simple projects as if I was using L2S I could've just done tostring on method id in my original code (not the code posted in the original question) and all would've been fine.
hermiod