Проблема NullReferenceException с ASP.NET MVC Textbox HtmlHelper - PullRequest
8 голосов
/ 06 мая 2009

У меня есть следующий код в строго типизированном представлении в моем приложении:

<td>
<label for="TriageStartDate">Triage Start:</label>
<%= Html.TextBox("TriageStartDate", crit.TriageStartDate, new { maxlength = 10, size = 12 } )%>
<%= Html.ValidationMessage("TriageStartDate", "*") %>
</td>

Переменная crit передается во ViewData и преобразуется в строго типизированный объект в представлении с использованием:

   PatientSearchCriteria crit = (PatientSearchCriteria)ViewData["criteria"];       

Свойство TriageStartDate является строковым свойством, определенным для объекта следующим образом:

public string TriageStartDate { get; set; }

У меня есть подпрограмма проверки в бизнес-объекте, которая проверяет это свойство на недопустимые даты. Процедура проверки вызывается в моем контроллере, и в контроллере я добавляю ModelError в ModelState при обнаружении недопустимой даты (например, «4/34/2009»). Это должно привести к повторному отображению представления, а также к выводу сводной информации о проверке и сообщения.

Однако код падает в строке Html.TextBox с необработанным исключением NullReferenceException. Код only дает сбой при вводе недопустимых дат, что, вероятно, не должно иметь значения, поскольку свойство в любом случае является строкой, и оно должно просто отображать недопустимую дату в текстовом поле.

Есть идеи, что здесь может происходить? Я думал, что это может быть Html.Encode, но действительные даты отображаются без суеты. Когда я разбиваю эту строку в режиме отладки, я вижу значение «4/34/2009» в свойстве TriageStartDate, а сама переменная крит не равна нулю, поэтому мне интересно, какой объект равен нулю?

Кстати, первые несколько строк трассировки стека выглядят так:

[NullReferenceException: Object reference not set to an instance of an object.]
   System.Web.Mvc.HtmlHelper.GetModelStateValue(String key, Type destinationType) +63
   System.Web.Mvc.Html.InputExtensions.InputHelper(HtmlHelper htmlHelper, InputType inputType, String name, Object value, Boolean useViewData, Boolean isChecked, Boolean setId, Boolean isExplicitValue, IDictionary`2 htmlAttributes) +519
   System.Web.Mvc.Html.InputExtensions.TextBox(HtmlHelper htmlHelper, String name, Object value, IDictionary`2 htmlAttributes) +34
   System.Web.Mvc.Html.InputExtensions.TextBox(HtmlHelper htmlHelper, String name, Object value, Object htmlAttributes) +62

Вот мой проверочный код (который может не быть красивым). В бизнес-объекте:

public override IEnumerable<ValidationError> GetValidationErrors()
{
    // check for valid start date
    if (!String.IsNullOrEmpty(TriageStartDate))
    {
        DateTime critStartDate;
        if (!DateTime.TryParse(TriageStartDate, out critStartDate))
            yield return new ValidationError(String.Format("Invalid triage start date specified: {0}", TriageStartDate), "TriageStartDate");
    }

    // check for valid end date
    if (!String.IsNullOrEmpty(TriageEndDate))
    {
        DateTime critEndDate;
        if (!DateTime.TryParse(TriageEndDate, out critEndDate))
            yield return new ValidationError(String.Format("Invalid triage end date specified: {0}", TriageEndDate), "TriageEndDate");
    }

    // verify that end date follows start date if both are specified
    if (!String.IsNullOrEmpty(TriageStartDate) && !String.IsNullOrEmpty(TriageEndDate))
    {
        DateTime startDate;
        DateTime endDate;

        if (DateTime.TryParse(TriageStartDate, out startDate) && DateTime.TryParse(TriageEndDate, out endDate))
        {
            if (startDate > endDate)
                yield return new ValidationError("Triage start date must be before end date", "_FORM");
        }
    }

    yield break;
}

В контроллере:

    // validate search criteria
    if (!criteria.IsValid)
    {
        foreach (ValidationError ve in criteria.GetValidationErrors())
        {
            ModelState.AddModelError(ve.PropertyName, ve.ErrorMessage);
        }
    }

Спасибо за любые подсказки!


Благодаря предложениям Крейга я обновил код контроллера следующим образом, и исключение нулевой ссылки пропало. Решение сработало, но я не уверен, что понимаю обоснование, так как значение, которое пользователь пытался ввести, уже сохранено в объекте модели, и у меня есть другие представления и контроллеры в проекте, которые отображают ошибки проверки таким же образом без любые вопросы. Но, эй, если это работает ...

    // validate search criteria
    if (!criteria.IsValid)
    {
        foreach (ValidationError ve in criteria.GetValidationErrors())
        {
            ModelState.AddModelError(ve.PropertyName, ve.ErrorMessage);
            ModelState.SetModelValue(ve.PropertyName, form.ToValueProvider()[ve.PropertyName]);
        }

    }

Ответы [ 3 ]

9 голосов
/ 06 мая 2009

После вызова AddModelError вам нужно вызвать SetModelValue . Это должно исправить нулевую ссылку.

1 голос
/ 21 августа 2009

ссылка, которую я нашел полезной в объяснении этого http://forums.asp.net/t/1380609.aspx

1 голос
/ 31 мая 2009

Я столкнулся с этим, когда печатал почти идентичный вопрос / проблему. (т. е. при рендеринге моего представления возникала таинственная исключительная ситуация NullReferenceException, когда пользовательское значение не прошло проверку в определенном поле.

Другой обходной путь, который я обнаружил, - это явно генерировать Html в представлении, а не позволять HtmlHelper выполнять эту работу.

Например: <%= Html.TextArea("FieldName", Model.FieldName) %> выдаст исключение, но <textarea id="FieldName" name="FieldName"><%= Model.FieldName ></textarea> будет отлично работать.

Спасибо за публикацию оригинального вопроса, так как теперь мне нужно еще немного изучить SetModelValue, чтобы увидеть, какой из двух подходов является лучшим решением ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...