views:

460

answers:

1

This question is related to another I ask recently, it can be found here for some background information.

Here is the code in the Edit ActionResult:

    public virtual ActionResult Edit(int id)
    {
        ///Set data for DropDownLists.
        ViewData["MethodList"] = tr.ListMethods();
        ViewData["GenderList"] = tr.ListGenders();
        ViewData["FocusAreaList"] = tr.ListFocusAreas();
        ViewData["SiteList"] = tr.ListSites();
        ViewData["TypeList"] = tr.ListTalkbackTypes();
        ViewData["CategoryList"] = tr.ListCategories();

        return View(tr.GetTalkback(id));
    }

I add lists to the ViewData to use in the dropdownlists, these are all IEnumerable and are all returning values.

GetTalkback() returns an Entity framework object of type Talkback which is generated from the Talkback table.

The DropDownListFor code is:

<%: Html.DropDownListFor(model=>model.method_id,new SelectList(ViewData["MethodList"] as IEnumerable<SelectListItem>,"Value","Text",Model.method_id)) %>

The record I am viewing has values in all fields. When I click submit on the View, I get an Object reference not set to an instance of an object. error on the above line.

There are a number of standard fields in the form prior to this, so the error is only occurring on dropdown lists, and it is occurring on all of them.

Any ideas? This is my first foray in to MVC, C#, and Entity so I am completely lost!

+1  A: 

If you have [HttpPost] method like that

[HttpPost]
public ActionResult Edit(Talkback model)
{
    //Do something with model
    return View(model);
}

You have to fill ViewData again. If you don't do it, you'll have Object reference not set to an instance of an object errors.

The best thing to do would be to follow POST-REDIRECT-GET patter and do it like that:

[HttpPost]
public ActionResult Edit(Talkback model)
{
    //Do something with model
    return RedirectToAction("Edit", new { id = model.id });
}

You'll have ViewData filled again by [HttpGet] method.

LukLed
Now I get 'An object with a null EntityKey value cannot be attached to an object context.' It looks like an empty Talkback is getting passed back to the controller rather than the one I sent to the Edit View on the HTTPGet. The default HTTPPost signature is 'int id, FormCollection collection' which I changed to Talkback model, is there some extra work I have to do in the view to get this to hook up?
hermiod
@hermiod: You get back only what you placed in form. You don't get whole model. Is `model.Id` set in postback? How is property with id called?
LukLed
I am passing in a Talkback object on the HTTPGet ActionResult for Edit. All fields are displayed on the form, including the ID field, which is called talkback_id in the Talkback object. Bar my changing of some fields to be dropdowns, all code on the form is default generated. The BeginForm for the page is default: Html.BeginForm(). I have seen examples of this being changed, is that what I need to do here? Apologies for my almost total ignorance on the subject, I'm still learning.
hermiod
@hermiod: You have to make sure that `name` of html input elements matches name of properties in your model (`Talkback`). If names don't match, it will not work as expected.
LukLed
The input names are all correct. I am using TextboxFor, EditorFor, and DropDownListFor so these are set automatically. I have checked in the output HTML just to be sure and they are all correct.
hermiod
I have changed the Edit ActionResult back to its original signature (int id, FormCollection formValues) and the model is now coming back as expected. I then retrieve the record back from the database and use UpdateModel() which is making the required changes to the retrieved object and the EntityState of the object is changed to modified. However, when I call SaveChanges on my Entities DataContext, the changes are not being persisted. Frustratingly, there are no errors.
hermiod
Got it! I was calling SaveChanges on a different instance of the Context so it didn't pick up the changes as they were happening on a different instance!What a donut! Thanks for your help LukLed.
hermiod
@hermiod: Great it works. Think about using one context per request, you'll have no such problems.
LukLed