views:

19

answers:

0

So I have some drop down lists in a view (apologies for the wall of code, thought it better to post to much than not enough):

//...blah...
    <%=Html.DisplayFor(m=>m.PlanType.PlanTypeType) %>
    <%=Html.DisplayFor(m=>m.YearLevel.YearLevelName) %>
    <%=Html.DisplayFor(m=>m.Subject.Subject1) %>
//..moreblah...

rendered via an editor template (SelectList.ascx):

    <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<SelectList>" %>
    <div class="editor-label">
        <%= Html.LabelFor(m => m) %>
    </div>
    <div class="editor-field">
        <%= Html.DropDownListFor(m => m, Model,"Select an Item...") %>
        <%= Html.ValidationMessageFor(m => m) %>
    </div>

And a User View:

    public class PlanView
    {
        public Plan Plan { get; private set; }

        [UIHint("SelectList")]
        [DisplayName("Plan Type")]
        public SelectList PlanType { get; private set; }

        [UIHint("SelectList")]
        [DisplayName("Year Level")]
        public SelectList YearLevel { get; private set; }

        [UIHint("SelectList")]
        [DisplayName("Subject")]
        public SelectList Subject { get; private set; }

        public PlanView(Plan plan)
        {
            Plan = plan;

            PlanTypeRepository PTR = new PlanTypeRepository();
            SubjectRepository SR = new SubjectRepository();
            YearLevelRepository YLR = new YearLevelRepository();

            PlanType = new SelectList(PTR.GetAll(), "PlanTypeID", "PlanTypeType", plan.PlanTypeID);
            YearLevel = new SelectList(YLR.GetAll(), "YearLevelID", "YearLevelName", plan.PlanYearLevelID);
            Subject = new SelectList(SR.GetAll(), "SubjectID", "Subject1", plan.PlanSubjectID);
        }

        public PlanView()
        { }
    }

And the controller:

[HttpPost]
public ActionResult Edit(int id, FormCollection collection)
{
    Plan plan = PR.GetSingle(id);
    PlanView pv = new PlanView(plan);
    try
    {
        plan.PlanAuthor = collection["Plan.PlanAuthor"];
        plan.PlanName = collection["Plan.PlanName"];
        plan.PlanMapID = Convert.ToInt32(collection["Plan.PlanMapID"]);
        plan.PlanTemplateID = Convert.ToInt32(collection["Plan.PlanTemplate"]);

        plan.PlanTypeID = Convert.ToInt32(collection["PlanType"]);
        plan.PlanSubjectID = Convert.ToInt32(collection["Subject"]);
        plan.PlanYearLevelID = Convert.ToInt32(collection["YearLevel"]);
        //UpdateModel(plan); 
        PR.Save();
        return RedirectToAction("Details", new { id = pv.Plan.PlanID });
    }
    catch
    {
        return View(pv);
    }
}

Which works. But i want to use UpdateModel() (currently commented out) in case i want to add any more fields, and also (mainly) cos i want to know how to do it. And i cant because the select lists return strings and the LINQ is expecting ints. So i have gathered that i need to write a model binder to convert the strings to ints. My attempt:

public class DropDownListBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext modelBindingContext)
    {
        string key = modelBindingContext.ModelName;
        ValueProviderResult val = modelBindingContext.ValueProvider.GetValue(key);

        try
        {
            if (val != null && !string.IsNullOrEmpty(val.AttemptedValue))
            {
                modelBindingContext.ModelState.SetModelValue(key, val);

                int number;

                if (int.TryParse(val.RawValue.ToString(), out number))
                {
                    return number;
                }
                throw new Exception("Borked :(");
            }
            throw new Exception("Borked :(");
        }
        catch (Exception e)
        {
            modelBindingContext.ModelState.AddModelError(key, e.Message);
            return null;
        }
    }
}

And in global.asax:

    protected void Application_Start()
    {
        RegisterRoutes(RouteTable.Routes);
        ModelBinders.Binders.Add(typeof(SelectList), new DropDownListBinder());
    }

Now if i comment out all the collection[key] manual updates in the controller and use UpdateModel() it dies in the arse saying that the data is invalid (which it is). If i place a breakpoint int the model binder it never fires so the model binder is not even excecuted.

So, am i missing something? Going about this all arse about? Thanks Internet!