У меня есть следующий код в строго типизированном представлении в моем приложении:
<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]);
}
}