Tom
Tom

Reputation: 63

ModelState.IsValid is always true

As is typical in MVC, I have a View, a Model, and a Controller.

The View contains a form:

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    @Html.HiddenFor(m => m.Id)
    <ul class="fieldlist">
        <li>
            @Html.LabelFor(m =>m.Email)
            @Html.TextBoxFor(m => m.Email)
            @Html.ValidationMessageFor(m => m.Email)
        </li>
        <li>
            <div class="row">
                <div class="col-md-6">
                    @Html.LabelFor(m => m.FirstName)
                    @Html.TextBoxFor(m => m.FirstName)
                    @Html.ValidationMessageFor(m => m.FirstName)
                </div>
                <div class="col-md-6">
                    @Html.LabelFor(m => m.LastName)
                    @Html.TextBoxFor(m => m.LastName)
                    @Html.ValidationMessageFor(m => m.LastName)
                </div>
            </div>
        </li>
        <li>
            @Html.LabelFor(m => m.PhoneNumber)
            @Html.TextBoxFor(m => m.PhoneNumber)
            @Html.ValidationMessageFor(m => m.PhoneNumber)
        </li>
        <li>
            <div Class="row">
                <div Class="col-md-2">
                    <input type="submit" value="Save" />
                </div>
            </div>
        </li>
    </ul>
}

The model looks like this:

public class UserAdminUserViewModel
{
    [Display(Name = "User Database ID"), DataType(DataType.Text)]
    public string Id { get; set; }
    [Display(Name = "Full Name")]
    public string Name { get { return FirstName + " " + LastName; } }
    [Required()]
    [Display(Name = "First Name"), DataType(DataType.Text)]
    public string FirstName { get; set; }
    [Required()]
    [Display(Name = "Last Name"), DataType(DataType.Text)]
    public string LastName { get; set; }
    [Required()]
    [Display(Name = "Email Address"), DataType(DataType.EmailAddress)]
    public string Email { get; set; }
    [Display(Name = "Telephone Number"), DataType(DataType.Text)]
    public string PhoneNumber { get; set; }
}

And the controller to receive the updates:

[HttpPost,ValidateAntiForgeryToken]
public ActionResult User(UserAdminUserViewModel model)
{
    if (ModelState.IsValid)
    {
        // do something, apply the updates to the database, presumably
    }
    return View(model);
}

...but ModelState.IsValid is always true. The controller is receiving the entered information, but it appears that no validation is taking place. I have tried:

TryUpdateModel<UserAdminUserViewModel>(model);

and

UpdateModel<UserAdminUserViewModel>(model);

I'm not sure I see how these would work, but they were the first suggestions I came across. No dice. Still valid regardless of the data in 'model'. I also tried:

System.ComponentModel.DataAnnotations.Validator.ValidateObject(model, new System.ComponentModel.DataAnnotations.ValidationContext(model));

More promising, but still doesn't work. I also tried the more verbose approach:

System.ComponentModel.DataAnnotations.ValidationContext valContext = new System.ComponentModel.DataAnnotations.ValidationContext(model, null, null);
List<System.ComponentModel.DataAnnotations.ValidationResult> valResults = new List<System.ComponentModel.DataAnnotations.ValidationResult>();
System.ComponentModel.DataAnnotations.Validator.TryValidateObject(model, valContext, valResults, true);
foreach(System.ComponentModel.DataAnnotations.ValidationResult result in valResults)
{
    this.ModelState.AddModelError(result.MemberNames.FirstOrDefault() ?? string.Empty, result.ErrorMessage);
}

...which also didn't work. 'valResults', which should contain any errors in the state of the model, is never filled; no validation is happening.

Upvotes: 1

Views: 1903

Answers (2)

zgood
zgood

Reputation: 12611

I would use this for email validation:

@using using System.ComponentModel.DataAnnotations;

[Required]
[EmailAddress]
[Display(Name = "Email Address")]
public string Email { get; set; }

Please see this StackOverflow post

However, EmailAddressAttribute adds server-side validation on top of that. I.e. there is no server-side validation if you only use DataTypeAttribute!

Upvotes: 2

Yurii N.
Yurii N.

Reputation: 5703

If the problem with incorrect email address, here's the solution:

[Email(ErrorMessage = "Invalid Email Address")]
[Required()]
[Display(Name = "Email Address"), DataType(DataType.EmailAddress)]
public string Email { get; set; }

DataType(DataType.EmailAddress) means only how to show textbox on client-side, while Email attribute does actual validation.

Upvotes: 0

Related Questions