ASP.NET MVC: сообщения проверки, установленные в TryUpdateModel, не отображают ValidationSummary - PullRequest
2 голосов
/ 01 сентября 2009

Я пытался следовать учебным пособиям и примерам в Интернете, таким как Блог Дэвида Хейдена и официальные ASP.Net MVC Tutorials , но я не могу ' t получить приведенный ниже код для отображения фактических ошибок проверки. Если у меня есть вид, который выглядит примерно так:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MvcApplication1.Models.Parent>" %>

<%-- ... content stuff ... --%>

<%= Html.ValidationSummary("Edit was unsuccessful. Correct errors and retry.") %>
<% using (Html.BeginForm()) {%>

<%-- ... "Parent" editor form stuff... --%>

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

<%-- etc... --%>

Для класса модели, который выглядит следующим образом:

public class Parent
{
    public String FirstName { get; set; }
    public String LastName { get; set; }
    public int Age { get; set; }
    public int Id { get; set; }
}

Всякий раз, когда я ввожу недопустимый возраст (так как возраст объявлен как целое число), например «xxx» (не целое число), представление действительно правильно отображает сообщение «Редактирование не удалось. Исправьте ошибки и повторите попытку "в верхней части экрана, а также выделив текстовое поле Age и поставьте рядом с ним красную звездочку, указывающую на ошибку. Тем не менее, список сообщений об ошибках не отображается с ValidationSummary. Когда я выполняю свою собственную проверку (например, для LastName ниже), сообщение отображается правильно, но встроенная проверка TryUpdateModel, похоже, не отображает сообщение, когда поле имеет недопустимое значение.

Вот действие, вызванное в моем коде контроллера:

    [AcceptVerbs(HttpVerbs.Post)] 
    public ActionResult EditParent(int id, FormCollection collection)
    {
        // Get an updated version of the Parent from the repository:
        Parent currentParent = theParentService.Read(id);

        // Exclude database "Id" from the update:
        TryUpdateModel(currentParent, null, null, new string[]{"Id"});
        if (String.IsNullOrEmpty(currentParent.LastName))
            ModelState.AddModelError("LastName", "Last name can't be empty.");
        if (!ModelState.IsValid)
            return View(currentParent);

        theParentService.Update(currentParent);
        return View(currentParent);
    }

Что я пропустил?

1 Ответ

2 голосов
/ 01 сентября 2009

Я скачал и посмотрел на исходный код ASP.NET MVC v1.0 от Microsoft и обнаружил, что, случайно или намеренно, нет способа сделать то, что я хочу делай, по крайней мере по умолчанию. Очевидно, что во время вызова UpdateModel или TryUpdateModel, если проверка целочисленного значения (например) завершается неудачно, ErrorMessage не устанавливается явно в ModelError, связанном с ModelState, для неверного значения, а вместо этого устанавливается свойство Exception. Согласно коду из MVC ValidationExtensions, следующий код используется для извлечения текста ошибки:

string errorText = GetUserErrorMessageOrDefault(htmlHelper.ViewContext.HttpContext, modelError, null /* modelState */);

Обратите внимание, что передан нулевой параметр для modelState. Затем метод GetUserErrorMEssageOrDefault начинается следующим образом:

private static string GetUserErrorMessageOrDefault(HttpContextBase httpContext, ModelError error, ModelState modelState) {
    if (!String.IsNullOrEmpty(error.ErrorMessage)) {
        return error.ErrorMessage;
    }
    if (modelState == null) {
        return null;
    }

    // Remaining code to fetch displayed string value...
}

Итак, если свойство ModelError.ErrorMessage является пустым (что я проверял, что оно происходит при попытке установить нецелое значение для объявленного int), MVC продолжает проверять ModelState, который, как мы уже обнаружили, равен нулю, таким образом, null возвращается для любого Exception ModelError. Итак, на данный момент, мои 2 лучшие идеи для обхода этой проблемы:

  1. Создайте пользовательское расширение Validation, которое корректно возвращает соответствующее сообщение, когда ErrorMessage не установлено, но установлено Exception.
  2. Создать функцию предварительной обработки, которая вызывается в контроллере, если ModelState.IsValid возвращает false. Функция предварительной обработки будет искать значения в ModelState, где ErrorMessage не установлено, но установлено исключение, и затем получать соответствующее сообщение, используя ModelState.Value.AttemptedValue.

Есть еще идеи?

...