I have an MVC application that is validating data and add errors to ModelState if it fails. I have a bunch of checkbox/drop-down pairs on a view where the checkbox indicates whether an item will be displayed on a public web site and, if that's unchecked,
the drop-down indicates the reason it won't be displayed. I'm validating like this:
private bool ValidateProcedureStatuses(FormCollection fields)
{
var procedureStatuses = from k in fields.AllKeys
where k.StartsWith("ProcedureStatus")
let dropDownName = k.Replace("Status", "Reason")
select new
{
CheckBoxName = k,
DropDownName = dropDownName,
Published = fields[k].StartsWith("true"),
Reason = fields[dropDownName]
};
foreach (var procedureStatus in procedureStatuses)
{
if (!procedureStatus.Published && string.IsNullOrEmpty(procedureStatus.Reason))
{
this.ModelState.AddModelError(procedureStatus.DropDownName, "A reason must be provided for unpublishing a procedure.");
}
}
return this.ModelState.IsValid;
}
Now, if I don't add the error to ModelState all is well. If I add the error to ModelState with a different name all is well. Using the code above though, a NullReferenceException is thrown when Html.DropDown is called, seemingly when it's trying to determine whether to use a style that indicates an error. Here's the call stack:
I've got Framework debugging on and I've traced execution as far as the GetModelStateValue method but I can't really see what's happening in there because it says that nothing can be evaluated because the code is optimised.
My theory is that it has something to do with control names that don't correspond to a model property name. To test this, I made some adjustments to some other code that was successfully showing validation errors against a drop-down list. The view was
for creating an Area Patient Access Coordinator and the drop-down listed Area Health Services. The control was named AreaID, which was the common field, and it worked fine. I changed the name of the control to "AreaIDx" and assigned the list of Areas to
ViewData["AreaIDx"] and the view still displayed correctly. When I tried to save without selecting an Area though, the error was added to ModelState state and then I got the very same NullReferenceException when I tried to redisplay the view.
If anyone knows what I'm doing wrong or a workaround for this issue, your advioce would be gratefully accepted.
I searched before posting but apparently not very well. After posting I refined my serahc and found some useful information. For the moment I'm using this code as a workaround:
this.ModelState.AddModelError(procedureStatus.DropDownName, "A reason must be provided for unpublishing a procedure.");
// This is required to avoid a NullReferenceException when binding the control.
this.ModelState.SetModelValue(procedureStatus.DropDownName, new ValueProviderResult(string.Empty, string.Empty, null));
That seems like a bit of a hack though, so I'm planning to do some reading on custom model binders. Any constructive comments are still welcome.
jmcilhinney
Member
2 Points
15 Posts
NullReferenceException when field in error is not a property of Model
Nov 15, 2009 05:41 AM|LINK
I have an MVC application that is validating data and add errors to ModelState if it fails. I have a bunch of checkbox/drop-down pairs on a view where the checkbox indicates whether an item will be displayed on a public web site and, if that's unchecked, the drop-down indicates the reason it won't be displayed. I'm validating like this:
private bool ValidateProcedureStatuses(FormCollection fields) { var procedureStatuses = from k in fields.AllKeys where k.StartsWith("ProcedureStatus") let dropDownName = k.Replace("Status", "Reason") select new { CheckBoxName = k, DropDownName = dropDownName, Published = fields[k].StartsWith("true"), Reason = fields[dropDownName] }; foreach (var procedureStatus in procedureStatuses) { if (!procedureStatus.Published && string.IsNullOrEmpty(procedureStatus.Reason)) { this.ModelState.AddModelError(procedureStatus.DropDownName, "A reason must be provided for unpublishing a procedure."); } } return this.ModelState.IsValid; }I'm then trying to display that error like so:
<% object htmlAttributes; if (Model.Published) { htmlAttributes = new { disabled = "disabled", onchange = "syncChildDropDowns(this, 'Procedure', 'Facility');" + "syncChildDropDowns(this, 'Procedure', 'Doctor')" }; } else { htmlAttributes = new { onchange = "syncChildDropDowns(this, 'Procedure', 'Facility');" + "syncChildDropDowns(this, 'Procedure', 'Doctor')" }; } Response.Write(Html.DropDownList("ProcedureReason_" + controlSuffix, Model.Reasons, string.Empty, htmlAttributes)); %> <%= Html.ValidationMessage("ProcedureReason_" + controlSuffix, "*")%>Now, if I don't add the error to ModelState all is well. If I add the error to ModelState with a different name all is well. Using the code above though, a NullReferenceException is thrown when Html.DropDown is called, seemingly when it's trying to determine whether to use a style that indicates an error. Here's the call stack:
I've got Framework debugging on and I've traced execution as far as the GetModelStateValue method but I can't really see what's happening in there because it says that nothing can be evaluated because the code is optimised.
My theory is that it has something to do with control names that don't correspond to a model property name. To test this, I made some adjustments to some other code that was successfully showing validation errors against a drop-down list. The view was for creating an Area Patient Access Coordinator and the drop-down listed Area Health Services. The control was named AreaID, which was the common field, and it worked fine. I changed the name of the control to "AreaIDx" and assigned the list of Areas to ViewData["AreaIDx"] and the view still displayed correctly. When I tried to save without selecting an Area though, the error was added to ModelState state and then I got the very same NullReferenceException when I tried to redisplay the view.
If anyone knows what I'm doing wrong or a workaround for this issue, your advioce would be gratefully accepted.
jmcilhinney
Member
2 Points
15 Posts
Re: NullReferenceException when field in error is not a property of Model
Nov 15, 2009 08:35 AM|LINK
I searched before posting but apparently not very well. After posting I refined my serahc and found some useful information. For the moment I'm using this code as a workaround:
That seems like a bit of a hack though, so I'm planning to do some reading on custom model binders. Any constructive comments are still welcome.levib
Star
7594 Points
1086 Posts
AspNetTeam
Re: NullReferenceException when field in error is not a property of Model
Nov 16, 2009 02:37 AM|LINK
Known bug in MVC 1, fixed in MVC 2.