Проверка ASP.NET MVC создает исключение NullReferenceException для пустого списка - PullRequest
4 голосов
/ 31 июля 2009

У меня есть два списка, один для доступных серверов и один для выбранных серверов. Пользователь перемещает элементы из первого поля во второе, чтобы указать их выбор.

<table id="ServerLists" style="width: 100%;">
  <tr>
    <td style="width: 40%;">
      <%=Html.ListBox("AvailableServerList", Model.AvailableServerList, New With {.size = 8, .ondblclick = "addServer();"})%>
    </td>
    <td style="width: 20%;">
      <button type="button" onclick="addAll();">Add All &gt;&gt;</button>
      <button type="button" onclick="addServer();">Add &gt;</button>
      <button type="button" onclick="removeServer();">&lt; Remove</button>
      <button type="button" onclick="removeAll();">&lt;&lt; Remove All</button>
    </td>
    <td style="width: 40%;">
      <%=Html.ListBox("SelectedServerList", Model.SelectedServerList, New With {.size = 8, .ondblclick = "removeServer();"})%>
    </td>
  </tr>
</table>

Если во второй список не добавлено ни одного сервера, я добавляю ошибку в ModelState.

Проблема заключается в том, что если в списке нет записей, MVC выдает исключение NullReferenceException при визуализации представления с предупреждениями проверки.

[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.SelectExtensions.SelectInternal(HtmlHelper htmlHelper, String optionLabel, String name, IEnumerable`1 selectList, Boolean allowMultiple, IDictionary`2 htmlAttributes) +155  
   System.Web.Mvc.Html.SelectExtensions.ListBox(HtmlHelper htmlHelper, String name, IEnumerable`1 selectList, Object htmlAttributes) +62  
   ASP.views_serveraccess_create_aspx.__RendercMain(HtmlTextWriter __w, Control parameterContainer) in C:\Documents and Settings\nfoster\My Documents\Visual Studio Projects\Client Portal 3\Trunk\src\Stargate3.Web\Views\ServerAccess\Create.aspx:148  
   System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +256  
   System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +19  
   System.Web.UI.Control.Render(HtmlTextWriter writer) +10  
   System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +27
   System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +99
   System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +25
   System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +134
   System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +19
   System.Web.UI.Control.Render(HtmlTextWriter writer) +10
   System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +27
   System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +99
   System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +25
   ASP.views_shared_site_master.__Render__control1(HtmlTextWriter __w, Control parameterContainer) in C:\Documents and Settings\nfoster\My Documents\Visual Studio Projects\Client Portal 3\Trunk\src\Stargate3.Web\Views\Shared\Site.Master:97
   System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +256
   System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +19
   System.Web.UI.Control.Render(HtmlTextWriter writer) +10
   System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +27
   System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +99
   System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +25
   System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +134
   System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +19
   System.Web.UI.Control.Render(HtmlTextWriter writer) +10
   System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +27
   System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +99
   System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +25
   System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +134
   System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +19
   System.Web.UI.Page.Render(HtmlTextWriter writer) +29
   System.Web.Mvc.ViewPage.Render(HtmlTextWriter writer) +57
   System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +27
   System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +99
   System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +25
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1266

Кто-нибудь еще имел эту проблему? Есть ли обходные пути, которые я могу попробовать? Вероятно, мне придется вставить туда запись [выберите сервер], если не было сделано никаких решений, но было бы полезно исправить эту проблему.

РЕДАКТИРОВАТЬ: Добавлено действие контроллера в соответствии с просьбой

<AcceptVerbs(HttpVerbs.Post)> _
Function Create(ByVal collection As FormCollection) As ActionResult
  Dim acceptedFields() As String = {"StartTime", "EndTime", "ReasonForAccess", "WorkToBeDone", "RegressionPlan", "Servers", "AccessAccount", "Password"}
  Dim accessRequest As New ServerAccessRequest
  UpdateModel(Of ServerAccessRequest)(accessRequest, acceptedFields)
  If accessRequest.IsValid Then
    'TODO: Do database stuff here
    Return View("AccessRequestConfirmation")
  Else
    For Each violation In accessRequest.GetRuleViolations
      ModelState.AddModelError(violation.PropertyName, violation.ErrorMessage)
    Next
  End If
  Return View(New ServerAccessViewModel(accessRequest))
End Function

Ответы [ 3 ]

4 голосов
/ 31 июля 2009

См. Примечания к выпуску для ASP.NET MVC 2 Preview 1; очевидно, это (NullReferenceException при передаче нуля в состояние модели) является известной ошибкой в ​​ASP.NET MVC.

4 голосов
/ 22 августа 2009

Я думаю, что этот пост поможет вам (он исправил мою проблему, которая была очень похожа на вашу):

http://www.crankingoutcode.com/?aspxerrorpath=/2009/02/01/IssuesWithAddModelErrorSetModelValueWithMVCRC1.aspx

Вывод заключается в том, что для некоторых сценариев (кажется, что ошибки проверки для Html.ListBox являются одними из них) вам необходимо вызвать ModelState.SetModelValue ()

ModelState.SetModelValue ("EmailListDisplay", новый ValueProviderResult (registrationValues.EmailListDisplay, "", null));

ValueProviderResult заботится о NullReference, и вы получите ваши сообщения проверки на странице.

Странно, что записи Html.TextBox, похоже, не нуждаются в этом коде.

В любом случае, я надеюсь, что это поможет вам.

* 1016 Ред *

0 голосов
/ 31 июля 2009

Является ли ваш Model.SelectedServerList нулевым значением? Model.AvailableServerList, вероятно, представляет собой набор объектов, но я не знаю, является ли Model.SelectedServerList нулевым.

Если ничего не помогает, вы можете сделать, как вы говорите, и добавить фиктивную опцию «Пожалуйста, выберите сервер» во второй список.

РЕДАКТИРОВАТЬ: я бы рекомендовал переключиться на «строго типизированную сигнатуру метода» (что я в любом случае называю это) - иначе:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(ServerAccessViewModel data)
{
    // Do stuff

    return View(data);
}

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

EDIT2: мне не удалось воспроизвести ваше точное сообщение об ошибке. В то же время, я бы сказал, что использование цикла foreach вместо ListBox позволит вам лучше контролировать вывод и предотвратить исключение.

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