views:

299

answers:

1

We are in the process of migrating our ASP.NET MVC 1.0 web app to MVC 2.0 but we have run into a small snag.

In our report creation wizard, it is possible leave the Title text box empty and have it be populated with a generic title (in the post action).

The code that does the update on the model of the Title is:

            if (TryUpdateModel(reportToEdit, new[] { "Title" }))
            {
                //all ok here try to create (custom validation and attach to graph to follow)

                //if title is empty get config subject
                if (reportToEdit.Title.Trim().Length <= 0)
                    reportToEdit.Title = reportConfiguration.Subject;

                if (!_service.CreateReport(1, reportToEdit, SelectedUser.ID, reportConfigID, reportCategoryID, reportTypeID, deviceUnitID))
                    return RedirectToAction("Index");
            }

In MVC 1.0, this works correctly,the reportToEdit has an empty title if the textbox is empty, which is then populated with the Subject property.

In MVC 2.0 this fails/returns false.

If I add the line above:

UpdateModel(reportToEdit, new[] { "Title" });

it throws

System.InvalidOperationException was unhandled by user code
  Message="The model of type 'Footprint.Web.Models.Reports' could not be updated."
  Source="System.Web.Mvc"
  StackTrace:
       at System.Web.Mvc.Controller.UpdateModel[TModel](TModel model, String prefix, String[] includeProperties, String[] excludeProperties, IValueProvider valueProvider)
       at System.Web.Mvc.Controller.UpdateModel[TModel](TModel model, String[] includeProperties)
       at Footprint.Web.Controllers.ReportsController.Step1(FormCollection form) in C:\TFS Workspace\ExtBusiness_Footprint\Branches\apitts_uioverhaul\Footprint\Footprint.Web\Controllers\ReportsController.cs:line 398
       at lambda_method(ExecutionScope , ControllerBase , Object[] )
       at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters)
       at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
       at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
       at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClassd.<InvokeActionMethodWithFilters>b__a()
       at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
  InnerException: 

Reading the MVC2 Release notes I see this breaking change:

Every property for model objects that use IDataErrorInfo to perform validation is validated, regardless of whether a new value was set. In ASP.NET MVC 1.0, only properties that had new values set would be validated. In ASP.NET MVC 2, the Error property of IDataErrorInfo is called only if all the property validators were successful.

but I'm confused how this is affecting me. I'm using the entity framework generated classes.

Can anyone pinpoint why this is failing?

A: 

OK, I've used a little work around which does the job.

Instead of using the implicit bind of the FormCollection to the TryUpdateModel(), i now modify the forms, then pass that into the TryUpdateModel().

this is now the code:

            if (string.IsNullOrEmpty(form["Title"]))
                form["Title"] = reportConfiguration.Subject;

            //update model with remaining forms collection: serialnumber, description, gasfactor, samplerate, checkforpolling
            if (TryUpdateModel(reportToEdit, new[] { "Title" }, form))
            {
                ...etc

Hope this is useful to someone :)

Alastair Pitts