views:

903

answers:

3

I am having problems with MVC RC2 where upon validation failure, the failed field will throw a NullReferenceException when the view is passed back to the user.

A short term solution was found: which was to rename the Html.ValidationMessage to be different than the Target Form Field. This works!

BUT now the automatic highlighting is disconnected from the input field. (Out of the box behavour is to change the target field's CSS Class which makes it standout)

So...

What is the actual problem with my code? AND Why wont it allow my ValidationMessage and Form fields share the same names?

The code is throwing NullReferenceException when the following code is run:

View Code

<% using (Html.BeginForm()) { %>
   <fieldset>
     <h5>Terms and Conditions</h5>
     <p>
       <%= Html.CheckBox("Terms", false)%>
       <%= Html.ValidationMessage("Terms")%>
       I agree to the <a href="/signup/terms">Terms & Conditions.</a>
     </p>
   </fieldset>
   <input class="signup_button" type="submit" title="Sign Up" value="" />
<% } %>
<%= Html.ValidationSummary("Sign up wasn't successful.")%>

Controller Code

[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Index()
{
    return View();
}

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(FormCollection form)
{
    bool Terms = form["Terms"].ToString() == "true,false" ? true : false;

    if (Terms)
    {
        return RedirectToAction("Success", "Signup");
    }
    else 
    {
        ModelState.AddModelError("Terms", "Please agree to the Terms");
        ModelState.AddModelError("_FORM", "Terms not checked");
    }
    return View();
}

I can get the code to work if I omit the following:

ModelState.AddModelError("Terms", "Please agree to the Terms");

But with this, the checkbox throws the Null reference exception.

Any Ideas?

A: 

Looks like a short term answer is simply to rename the html.ValidationMessage to something else

<%= Html.ValidationMessage("TermsError")%>

And make sure the control uses the same name when adding an Error state

ModelState.AddModelError("TermsError", "Please agree to the Terms");

This fixes the issue for me. Still, I'm left wondering... what is the best naming convention for using the html.ValidationMessage?

Harry
This answer introduces an annoying problem where the textboxes are now nolonger changing colour to highlight the validation issue
Harry
A: 

In this case, why are you passing in form collection? Why not do this?

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(bool terms)
{
    if (terms)
    {
        return RedirectToAction("Success", "Signup");
    }
    else 
    {
        ModelState.AddModelError("Terms", "Please agree to the Terms");
        ModelState.AddModelError("_FORM", "Terms not checked");
    }
    return View();
}

That ought to work just fine.

Haacked
Hey Phil, I'm not sure that you read the question. This example is simplified as there are around 12 form fields
Harry
+3  A: 

Try this:

else 
{
    ModelState.AddModelError("Terms", "Please agree to the Terms");
    ModelState.SetModelValue("Terms", form.ToValueProvider()["Terms"]);
    ModelState.AddModelError("_FORM", "Terms not checked");
}

If that doesn't work, then please post the full stack for the exception.

Craig Stuntz
This worked! Now, can you explain why?
Harry
The API changed in RC 1 to support multiple messages/errors per name.
Craig Stuntz