views:

60

answers:

2

I have a simple form on an ASP.NET MVC site that I'm building. This form is submitted, and then I validate that the form fields aren't null, empty, or improperly formatted.

However, when I use ModelState.AddModelError() to indicate validation errors from my controller code, I get an error when my view is re-rendered. In Visual Studio, I get that the following line is highlighted as being the location of the error:

<%=Html.TextBox("Email")%>

The error is the following:

NullReferenceException was unhandled by user code - object reference not set to an instance of an object.

My complete code for that textbox is the following:

<p>
<label for="Email">Your Email:</label>
<%=Html.TextBox("Email")%>
<%=Html.ValidationMessage("Email", "*") %>
</p>

Here's how I'm doing that validation in my controller:

        try
        {
            System.Net.Mail.MailAddress address = new System.Net.Mail.MailAddress(email);
        }
        catch
        {
            ModelState.AddModelError("Email", "Should not be empty or invalid");
        }

return View();

Note: this applies to all of my fields, not just my Email field, as long as they are invalid.

+1  A: 

That's a horrible bug/feature (call in whatever) in ASP.NET MVC the helper that you may fix by calling SetModelValue like this:

ModelState.AddModelError("Email", "Should not be empty or invalid");
ModelState.SetModelValue("Email", new ValueProviderResult("raw value", "attempted value", CultureInfo.InvariantCulture));

By the way is there any reason you would write all this code when you could simply annotate your view model:

public class SomeViewModel
{
    [RegularExpression("Some bulletproof regex you could google to validate email address", ErrorMessage = "Should not be empty or invalid")]
    public string Email { get; set; }
}

and leave the data binder do the heavy lifting.

Darin Dimitrov
So, for the first code example: you have to have both lines, right? In other words, I first call AddModelError and then I call SetModelValue? Also, what are raw-value and attempted-value? Thanks.
Maxim Zaslavsky
Yes you need both lines. RawValue points to an object which has the the property used for updating. AttemptedValue stores what the user actually entered. I believe you may leave them blank.
Darin Dimitrov
Could you give an example of a RawValue, such as an email property? I'm sort of confused.
Maxim Zaslavsky
A: 

I am unable to reproduce.

Action

[HttpPost]
public ActionResult Index(string email)
{
    if (string.IsNullOrEmpty(email))
    {
        ModelState.AddModelError("Email", "Should not be empty or invalid");
    }
    return View();
}

View

    <%using (Html.BeginForm() { %>
    <p>
        <label for="Email">
            Your Email:</label>
        <%=Html.TextBox("Email")%>
        <%=Html.ValidationMessage("Email", "*") %>
        <input type="submit" />
    </p>
    <%} %>
Raj Kaimal