Метод проверки IValidatableObject не работает

У меня есть этот класс, используемый в MVC3...

Атрибуты проверки для каждого свойства работают должным образом, но когда вызывается метод проверки и возвращаются какие-либо результаты, он не отправляется обратно в форму. Кто-нибудь может помочь??

public class Register : IValidatableObject
{
    [DataType(DataType.Text)]
    [Display(Name = "District Name")]
    [Required(AllowEmptyStrings = false, ErrorMessage = "You must enter a District Name")]
    [StringLength(40, MinimumLength = 1, ErrorMessage = "District Name must be between 1 and 40 characters")]
    public string DistrictName { get; set; }

    [DataType(DataType.Text)]
    [Display(Name = "Url Quick Find")]
    [Required(ErrorMessage = "You must provide a Quick Find Name")]
    [StringLength(15, MinimumLength = 3, ErrorMessage = "Url Quick Find must be between 3 and 15 characters")]
    public string QuickFind { get; set; }

    [DataType(DataType.Text)]
    [Display(Name = "User name")]
    [Required(AllowEmptyStrings = false, ErrorMessage = "User name is requred")]
    [StringLength(10, MinimumLength = 1, ErrorMessage = "Url Quick Find must be between 1 and 10 characters")]
    public string Username { get; set; }

    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    [Required(AllowEmptyStrings = false, ErrorMessage = "Password is requred")]
    public string Password { get; set; }

    [DataType(DataType.Password)]
    [Display(Name = "Re-Enter Password")]
    [Required(AllowEmptyStrings = false, ErrorMessage = "You must re-enter your password to confirm you have entered it correctly")]
    public string PasswordConfirm { get; set; }

    [DataType(DataType.Text)]
    [Display(Name = "Display Name")]
    [Required(AllowEmptyStrings = false, ErrorMessage = "Display Name is requred")]
    [StringLength(20, MinimumLength = 1, ErrorMessage = "Display Name must be between 1 and 20 characters")]
    public string DisplayName { get; set; }

    [DataType(DataType.EmailAddress)]
    [Display(Name = "Email Address")]
    [Required(AllowEmptyStrings = false, ErrorMessage = "Email Address is requred")]
    [StringLength(50, MinimumLength = 4, ErrorMessage = "Email Address must be between 4 and 50 characters")]
    public string EmailAddress { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        Regex lettersOnly = new Regex("^[a-zA-Z]*$");

        if (!lettersOnly.IsMatch(QuickFind))
            yield return new ValidationResult("Only letters A - Z are allowed in the Quick Find", new string[] { "QuickFind" });

        if (!lettersOnly.IsMatch(QuickFind))
            yield return new ValidationResult("Only letters A - Z are allowed for your User name", new string[] { "Username" });

        if (Password != PasswordConfirm)
            yield return new ValidationResult("Passwords do not match", new string[] { "Password", "PasswordConfirm" });

    }
}

Код контроллера:

[HttpPost]
    public ActionResult Index(Register registration)
    {
        try
        {
            User newUser = RegistrationManager.Register(registration);
            RedirectToAction("Index", "District", newUser.ID);
        }
        catch (Exception ex)
        {
            ModelState.AddModelError("There has been an Error during Registration", ex.Message);
            RedirectToAction("Details", "Error", ex);
        }

        return View();
    }

Просмотреть код:

@model PubGames.Data.Register
@{
    ViewBag.Title = "Register";
}
<h2>
    Register</h2>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")"     type="text/javascript"></script>
@using (Html.BeginForm())
{
    @Html.ValidationSummary(true)

    <div class="editor-label">
        @Html.LabelFor(model => model.DistrictName)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.DistrictName)
        @Html.ValidationMessageFor(model => model.DistrictName)
    </div>

    <div class="editor-label">
        @Html.LabelFor(model => model.QuickFind)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.QuickFind)
        @Html.ValidationMessageFor(model => model.QuickFind)
    </div>

    <div class="editor-label">
        @Html.LabelFor(model => model.Username)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.Username)
        @Html.ValidationMessageFor(model => model.Username)
    </div>

    <div class="editor-label">
        @Html.LabelFor(model => model.Password)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.Password)
        @Html.ValidationMessageFor(model => model.Password)
    </div>

    <div class="editor-label">
        @Html.LabelFor(model => model.PasswordConfirm)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.PasswordConfirm)
        @Html.ValidationMessageFor(model => model.PasswordConfirm)
    </div>

    <div class="editor-label">
        @Html.LabelFor(model => model.DisplayName)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.DisplayName)
        @Html.ValidationMessageFor(model => model.DisplayName)
    </div>

    <div class="editor-label">
        @Html.LabelFor(model => model.EmailAddress)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.EmailAddress)
        @Html.ValidationMessageFor(model => model.EmailAddress)
    </div>

    <p>
        <input type="submit" value="Register" />
    </p>
} 

person Andy Clark    schedule 29.12.2011    source источник
comment
Вам также необходимо показать нам соответствующий код в вашем контроллере и просмотреть.   -  person Erik Funkenbusch    schedule 29.12.2011
comment
Добавлен контроллер и код просмотра   -  person Andy Clark    schedule 29.12.2011
comment
К вашему сведению, вам действительно не нужно IValidatableObject для проверок, показанных в вашем примере кода; вы можете получить те же результаты, используя только аннотации данных: [RegularExpression(@"^[a-zA-Z]*$", ErrorMessage = "Only letters A - Z are allowed in {0}.")] и [Compare("Password", ErrorMessage = "Passwords do not match.")]. Аннотации данных также обеспечивают проверку на стороне клиента.   -  person Daniel Liuzzi    schedule 15.01.2012


Ответы (3)


Столько проблем...

Типичный метод Action выглядит следующим образом:

public ActionResult DoSomething(MyModel model)
{
    if (ModelState.IsValid)
    {
        return RedirectToAction("somethign");
    }
    return View(model);
}

Это делает несколько вещей, но в первую очередь возвращает состояние модели обратно в представление, если оно недействительно. Вы этого не делаете, и фактически вы даже не возвращаете модель обратно в представление. Вы не проверяете, действительно ли состояние, поэтому он попытается вызвать метод регистрации, даже если проверка не пройдена на стороне сервера. Вы также не возвращаете свои ActionResults, т.е. RedirectToAction, вы просто вызываете его.

person Erik Funkenbusch    schedule 29.12.2011

Вы не правильно перенаправляете. Вы должны вернуть RedirectToAction:

[HttpPost]
public ActionResult Index(Register registration)
{
    try
    {
        User newUser = RegistrationManager.Register(registration);
        return RedirectToAction("Index", "District", newUser.ID);
    }
    catch (Exception ex)
    {
        ModelState.AddModelError("There has been an Error during Registration", ex.Message);
        return RedirectToAction("Details", "Error", ex);
    }

    return View(registration);
}

Также при перенаправлении в случае исключения вы потеряете все ошибки, которые вы добавили в состояние модели.

person Darin Dimitrov    schedule 29.12.2011

Как вы имеете в виду «не отправлять обратно в форму» - вы имеете в виду, что ошибки не отображаются? Гарантировать

  1. У вас есть сводка проверки на странице
  2. Вы НЕ перенаправляете после своего поста.
  3. имейте в виду, что это не для проверки клиента (просто говоря, вы, возможно, уже знаете)
person Adam Tuliper - MSFT    schedule 29.12.2011