views:

747

answers:

1

Any ideas why this doesn't update but doesn't throw an error?

public ActionResult Edit(int id, [Bind(Exclude = "deptid")]FormCollection collection)
    {
        var department = _repository.ListOne(id); //Grabs record from linq to sql
        try
        {
            UpdateModel(department);
            _entities.SubmitChanges();

            // TODO: Add update logic here

            return RedirectToAction("Index");
        }
        catch
        {
            return View(department);
        }
    }
+2  A: 

Sometimes what may happen is an error is thrown somewhere inside of the MVC assembly which is not handled nicely, and which does not get copied into your model state as expected. Then, when you try to display in your view the Html.ValidationSummary, it doesn't show you the error, which can be very confusing. One example that can crash this model binding process I've written about here. Usually, after you figure out why this is happening, you can make the corrections to your code and not worry about it anymore.

I have the following code that I use to inspect during debugging, to let me hover over it at a breakpoint and see what is really going on:

public static IDictionary<string, string> GetModelStateErrors(this ViewDataDictionary viewDataDictionary)
{
    Dictionary<string, string> dict = new Dictionary<string, string>();
    foreach (var modelStateKey in viewDataDictionary.ModelState.Keys)
    {
        var modelStateValue = viewDataDictionary.ModelState[modelStateKey];
        foreach (var error in modelStateValue.Errors)
        {
            var errorMessage = error.ErrorMessage;
            var exception = error.Exception;
            if (!String.IsNullOrEmpty(errorMessage))
            {
                dict.Add(modelStateKey, "Egads! A Model Error Message! " + errorMessage);
            }
            if (exception != null)
            {
                dict.Add(modelStateKey, "Egads! A Model Error Exception! " + exception.ToString());
            }
        }
    }
    return dict;
}

Then, I can insert this after I try to UpdateModel, and set a breakpoint on it:

var x = ViewData.GetModelStateErrors();

Put this right after your call to UpdateModel. Hovering over the x will show you any unhandled exceptions in the model-binding process, if that is what is really the problem here.

Good luck!

Funka
P.S., this is also incredibly handy for when all you get in your `ValidationSummary` is the dreaded "A value is required." (i.e., no key or fieldname to help you figure out exactly _what_ it is that is required...)
Funka
I get a this type/namespace viewdatadictionary could not be found. Also, where the hell do you put that block of code? I am not used to this whole MVC thing
ATMILO
TryUpdateModel returns true but doesnt update
ATMILO
For some reason it doesn't like when I use this - var department = _repository.ListOne(id);It works if I use the direct linq query instead of referencing that class
ATMILO
if you put your cursor right at the last character of the word `ViewDataDictionary`, you can hit CTRL-dot (".") to open a list of suggestions for importing the correct namespace. This adds the appropriate "using" directive at the top of the file for you. As far as where you add this method, that is really up to you. You could create an "extensions" class (as I did) or you could even just put it somewhere inside your controller or base controller.
Funka
however it sounds like if TryUpdateModel is returning true, this isn't going to help you at all. As has already been suggested on this page, we would need you to show more of the code...
Funka