2013-10-25 3 views
7

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

<div> 
<input value="@Html.Raw(str)" /> 
</div> 

Это работает просто отлично:

<div> 
<input value="@str" /> 
</div> 

Как это делает:

<div> 
Values is: @Html.Raw(str) 
</div> 

Так что это не вопрос @ Html.Raw не в состоянии принять параметр NULL. Я не уверен, что именно он возвращает в этом случае; но он как-то отличается на одном сервере, чем на другом.

Оба имеют ту же версию System.Web.Mvc, хотя я не знаю, что другие DLL для проверки. System.Web.WebPages, которая является сборкой, которая должна содержать сбойный метод MVC, является той же версией на обоих серверах. Это версия MVC 4; .Net 4.5.

Как такое возможно? Ошибка возникает в методе WriteAttributeTo, хотя я даже не знаю, почему это будет вызвано здесь, поскольку оно использует стандартные теги HTML, а не помощник @ Html.TextBoxFor.

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

Вот полный трассировки стека:

в System.Web.WebPages.WebPageExecutingBase.WriteAttributeTo (String pageVirtualPath, TextWriter писатель, имя String, PositionTagged 1 prefix, PositionTagged 1 суффикс, AttributeValue [] значения) в System.Web.WebPages.WebPageExecutingBase.WriteAttributeTo (TextWriter писатель, имя String, PositionTagged 1 prefix, PositionTagged 1 суффикс, AttributeValue [] значения) на System.Web.WebPages.WebPageExecutingBase.WriteAttribute (имя строкового PositionTagged 1 prefix, PositionTagged 1 суффикс, AttributeValue [] значения) в ASP._Page_Views_AdminSurvey_TopDown_cshtml.Execute() в C: \ Windows \ Microsoft.NET \ Framework64 \ v4.0.30319 \ Temporary ASP.NET Files \ корень \ fdd62ffd \ 90d151d1 \ App_Web_xsolwitr. 2.cs: линия 0 в System.Web.WebPages.WebPageBase.ExecutePageHierarchy() в System.Web.Mvc.WebViewPage.ExecutePageHierarchy() в System.Web.WebPages.StartPage.ExecutePageHierarchy() в System.Web .WebPages.WebPageBase.ExecutePageHierarchy (WebPageContext PageContext, TextWriter писатель, WebPageRenderingBase StartPage) в System.Web.Mvc.ViewResultBase.ExecuteResult (ControllerContext контекст) в System.Web.Mvc.ControllerActionInvoker. <> c_ DisplayClass1a.b _17() на System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter (IResultFilter фильтр, ResultExecutingContext preContext, Func 1 continuation) at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func 1 продолжение) в System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters (ControllerContext controlContext, IList`1, ActionResult actionResult) в System.Web.Mvc.Async.AsyncControllerActionInvoker. <> c_ DisplayClass25.b _22 (IAsyncResult asyncResult) в System.Web.Mvc.Controller. <> c_ DisplayClass1d.b _18 (IAsyncResult asyncResult) в System.Web.Mvc.Async.AsyncResultWrapper. <> c_ DisplayClass4.b _3 (IAsyncResult ар) при System.Web.Mvc.Controller.EndExecuteCore (IAsyncResult AsyncResult) в System.Web.Mvc.Async.AsyncResultWrapper. <> c_ DisplayClass4.b _3 (IAsyncResult ar) по адресу System.Web.Mvc.MvcHandler. <> c_ DisplayClass6. <> c _DisplayClassb.b_ 4 (IAsyncResult asyncResult) в System.Web.Mvc.Async.AsyncResultWrapper. <> с _DisplayClass4.b__3 (IAsyncResult ар) при System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() на System.Web.HttpApplication.ExecuteStep (IExecutionStep шаг, Логическое & completedSynchronously)

+0

Значение строки равно нулю? Или что-то еще? Возможно, в этой строке есть какой-то юникод, который испортился с писателем. – Fals

+0

Это происходит только тогда, когда оно равно нулю. Протестировал его, просто используя null непосредственно вместо переменной; такой же результат. – GendoIkari

+0

Можете ли вы воспроизвести проблему во вновь созданном приложении MVC4 (только один контроллер с одним октановым видом), развернутым на вашем рабочем сервере? Или эта проблема существует только в вашем реальном приложении? Если вы можете перепрограммировать его, вы можете загрузить свою версию где-нибудь (github/skydrive/etc)? – nemesv

ответ

5

Благодаря помощи nemesv и Dave A, я смог отслеживать проблему. Это ответ на 2 части.

1) Причиной исключения оказалось, что существует ошибка в Бритва реализации объединения Html.Raw внутри HTML атрибута. Когда Razor View Engine попадается текст внутри HTML атрибут, он использует метод WebPageExecutingBase.WriteAttributeTo(), даже если это только в простом HTML. Раньше у меня создалось впечатление, что Razor View Engine обрабатывал только серверные команды (код, который поступает после символа @). Хотя оба значения Html.Raw и WriteAttibuteTo() допускают нулевые значения, требуется специальная обработка для обработки объединения 2, и этот код сбой, если было нулевое значение.

2) Это так был обновлен/зафиксирован в последнем выпуске System.Web.WebPages.dll, что приводит к второй части ответа. Проект ссылался на Ver 2.0.20505.0 этой DLL, и он был развернут в папке bin проекта. Эта версия содержит ошибку.

Но несмотря на то, что проект ссылался на проект, а в папке bin сервер тестирования не использовал эту версию DLL для привязки сборки. fuslog.exe показал, что он является обязательным для сборки, которая была зарегистрирована в GAC вместо, который был Ver 2.0.20710.0. Сервер QA имел это в GAC, а сервер производства - нет. Я не знал, что GAC переопределит DLL, находящуюся в папке bin.

Я обновил свой проект для ссылки на последние ASPNetMVC пакет, который включает в себя Ver 2.0.30506.0 из WebPages Dll.

2

Может ли это незначительное изменение количества номеров на самом деле изменить ситуацию?

Конечно, это может быть незначительная сборка, как правило, состоит из неразрывных изменений, но это не значит, что они не могут содержать ошибки. Похоже, проблема возникает в System.Web.WebPages.WebPageExecutingBase, поэтому, вероятно, можно с уверенностью предположить, что несоответствие версии System.Web.dll, вероятно, является источником проблемы.

Вы можете запустить обе библиотеки DLL через дизассемблер и посмотреть, есть ли какие-либо очевидные изменения в этой области и вокруг нее, однако, если вы знаете, что проблема исправлена ​​в более поздней версии, просто используйте это на своей машине развертывания.


Был issue в связи с Html.Raw не декодированием текста правильно, когда используется в качестве атрибута, который был зафиксирован в августе, не уверен, что это изменение между 2-й версиями, которые исправили проблему.

+0

Это похоже на то, что объясняет это, но этот код должен быть в System.Web.WebPages.dll, а не System.Web.dll. System.Web.WebPages.dll развернут в папке bin моего проекта, таким образом, идентичен на обоих серверах. Кроме того, наш prod-сервер имел ожидающий перезапуск и после перезагрузки System.Web.dll был обновлен; проблема все еще существует. – GendoIkari

+0

Я только что подтвердил, что на обоих серверах запущена обновленная версия этого конкретного кода. Test ")" /> правильно оставляет HTML-код незакодированным, что и устраняет проблему. – GendoIkari

1

Давайте углубимся в Razor View Engine:

Когда Действие Метод вызывает

return View() 

Метод View() возвращает ViewResult объекта. ViewResult Объект имеет ExecuteResult() метод - который отвечает за создание HTML документа.

Когда ExecuteResult() метод встречает помощника, как @Html.Raw, он проверяет контекст.В случае заполнения атрибутов Razor View Engine пытается быть умным (или не глупым) по следующим правилам и избегать ям. Метод, используемый для рендеринга значений атрибута, - WebPageExecutingBase.WriteAttributeTo().

Если вы ищете подписи для WriteAttributeTo(), вы увидите, что последние ParamArray. Опять же, мы изучаем абстрактные методы (не публикуются), но я подозреваю, что внедрение метода WriteAttributeTo() не учитывает нулевой массив и вызывает исключение.

+0

Действительно ли код не является открытым исходным кодом? http://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.WebPages/WebPageExecutingBase.cs. Я вижу, что если параметр ParamArray равен NULL, он, похоже, сломает его. Но разве это не должно быть в сборке system.web.webpages? В этом случае оба сервера имеют одинаковый код. – GendoIkari

+0

Но ваш ответ определенно полезен. Я никогда раньше не понимал, что Razor Engine работал именно так. Я понял, что серверный код (@) был просмотрен сервером; и остальное было оставлено как есть.Теперь я вижу, что движок фактически анализирует весь View и читает (затем выписывает) обычные HTML-теги. Это объясняет, почему WriteAttributeTo() будет вызываться, по крайней мере. Прежде чем я подумал, что это будет вызвано только для HTML-помощников. – GendoIkari

+0

Еще одна вещь, которая не ясна ... отлично работает. Это должно быть вызвано WriteAttributeValues ​​с тем же параметром NULL, не так ли? Похоже, что Html.Raw (null) просто возвращает null ... – GendoIkari

0

Очень интересная проблема, и я рад, что вы нашли свой ответ!

Просто быстро исправить, если по какой-то причине вы застряли в старой версии DLL - использовать нулевой оператор коалесцирующий ??, чтобы убедиться, что содержимое никогда не null

<div> 
    <input value="@Html.Raw(str ?? "")" /> 
</div> 
Смежные вопросы