Аргх! Почему система.Сеть.В MVC.HandleErrorInfo передается в мои представления?
Я испытываю довольно неприятную проблему. Мой сайт MVC работает нормально по большей части, но случайным образом выдает ошибку (которая показывает дружественную ошибку пользователю). Когда я проверяю журналы, это то, что я получаю:
System.InvalidOperationException: The model item passed into the dictionary is of type 'System.Web.Mvc.HandleErrorInfo' but this dictionary requires a model item of type 'BaseViewData'.
мгновения спустя тот же пользователь может нажать "Обновить", и страница загрузится нормально. Я застрял. ;(
Update: добавлена трассировка стека
System.Web.HttpUnhandledException: Exception of type 'System.Web.HttpUnhandledException' was thrown. ---> System.InvalidOperationException: The model item passed into the dictionary is of type 'System.Web.Mvc.HandleErrorInfo' but this dictionary requires a model item of type 'BaseViewData'.
at System.Web.Mvc.ViewDataDictionary`1.SetModel(Object value)
at System.Web.Mvc.ViewDataDictionary..ctor(ViewDataDictionary dictionary)
at System.Web.Mvc.HtmlHelper`1..ctor(ViewContext viewContext, IViewDataContainer viewDataContainer, RouteCollection routeCollection)
at System.Web.Mvc.ViewMasterPage`1.get_Html()
at ASP.views_shared_site_master.__Render__control1(HtmlTextWriter __w, Control parameterContainer)
at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children)
at System.Web.UI.Control.RenderChildren(HtmlTextWriter writer)
at System.Web.UI.Control.Render(HtmlTextWriter writer)
at System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter)
at System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter)
at System.Web.UI.Control.RenderControl(HtmlTextWriter writer)
at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children)
at System.Web.UI.Control.RenderChildren(HtmlTextWriter writer)
at System.Web.UI.Page.Render(HtmlTextWriter writer)
at System.Web.Mvc.ViewPage.Render(HtmlTextWriter writer)
at System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter)
at System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter)
at System.Web.UI.Control.RenderControl(HtmlTextWriter writer)
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
--- End of inner exception stack trace ---
at System.Web.UI.Page.HandleError(Exception e)
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
at System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
at System.Web.UI.Page.ProcessRequest()
at System.Web.UI.Page.ProcessRequestWithNoAssert(HttpContext context)
at System.Web.UI.Page.ProcessRequest(HttpContext context)
at ASP.views_shared_error_aspx.ProcessRequest(HttpContext context)
at System.Web.Mvc.ViewPage.RenderView(ViewContext viewContext)
at System.Web.Mvc.WebFormView.RenderViewPage(ViewContext context, ViewPage page)
at System.Web.Mvc.WebFormView.Render(ViewContext viewContext, TextWriter writer)
at System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult)
at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)
at System.Web.Mvc.Controller.ExecuteCore()
at System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext)
at System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext)
at System.Web.Mvc.MvcHandler.ProcessRequest(HttpContextBase httpContext)
at System.Web.Mvc.MvcHandler.ProcessRequest(HttpContext httpContext)
at System.Web.Mvc.MvcHandler.System.Web.IHttpHandler.ProcessRequest(HttpContext httpContext)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
4 ответов
здесь на страницы CodePlex объясняя, почему возникает эта ошибка.
цитата http://web.archive.org/web/20131004122626/http://aspnet.codeplex.com/workitem/1795 поскольку оригинальная ссылка мертва:
атрибут HandleError не должен хранить информацию об исключении в ViewData
когда
HandleErrorатрибут обрабатывает исключение, он хранит информацию об исключении вViewData. Это проблема, когдаError.aspxнаследует отsite.masterиsite.masterкласс объявляется следующим образом.public partial class Site : System.Web.Mvc.ViewMasterPage<SiteViewData> { }
SiteViewDataсодержит:public class SiteViewData { public String Title { get; set; } }каждой страницы
ViewDataкласс наследуется отSiteViewDataкласса и выглядит примерно такpublic class IndexViewData : SiteViewData { public String Message { get; set; } public String SupportedLanguages {get; set;} }этот подход позволяет писать код в
Site.Masterстраница следующим образом<title><%= Html.Encode(ViewData.Model.Title) %></title>к сожалению, когда возникает исключение, модель была заменено экземпляром
HandleErrorInfoкласса. Это вызываетInvalidOperationExceptionчтобы быть брошенным с информациейэлемент модели, переданный в словарь, имеет тип
System.Web.Mvc.HandleErrorInfoно этот словарь требует элементов модели типаIgwt.Boh.Website.Web.Controllers.SiteViewData.возможно ли новое
ErrorDataсвойство, которое будет добавлено вViewResultкласс для хранения экземпляра класса? СюдаViewDataне изменяется.шансы довольно хорошо, что любое исключение, брошенное в действие, произойдет после
IndexViewData(иSiteViewData) свойства уже инициализированы.закрыто 27 января 2010 года в 12:24 по
не будет исправлено - см. комментарии.
комментарии, упомянутые с "wontfix", от бывшего члена команды Microsoft, вместе с их предложением для работы вокруг него (выделено жирным шрифтом):
к моменту атрибута [HandleError] исполняет, мы потеряли ссылка на исходный объект ActionResult. Мы даже не знаем, вы все равно собирались показать вид - может быть, вы собирались перенаправить. Часть конвейера (ViewResult), которая была бы ответственным за передачу модели от контроллера к представлению является ушедший.
если возникает исключение, любая модель, над которой работает приложение вероятно, следует рассматривать как коррумпированные или недоступные в любом случае. лучшие практика нужно написать свой вид ошибки так, чтобы ни он, ни его зависимости (например, его главная страница) требуют оригинала модель.
мое решение для решения проблемы-удалить директиву @model в верхней части страницы макета, а затем выполнить некоторые проверки, где я обычно ожидаю увидеть мою модель для переключения между различными моделями, которые могут быть переданы, например
@if (Model is System.Web.Mvc.HandleErrorInfo)
{
<title>Error</title>
}
else if (Model.GetType() == typeof(MyApp.Models.BaseViewModel))
{
<meta name="description" content="@Model.PageMetaDescription">
<title>@Model.PageTitleComplete</title>
}
я только что отследил аналогичную проблему в своем приложении и хотел описать исправление для меня. В моем случае я получал следующее исключение:
System.InvalidOperationException: The model item passed into the dictionary is of
type 'System.Web.Mvc.HandleErrorInfo', but this dictionary requires a model item of
type 'Web.Models.Admin.Login'.
и я использовал [HandleError] для маршрута ошибок ~/Shared/Error.cshtml
что случилось [по крайней мере в моем случае] было:
~/Shared/Error.cshtml had Layout = "~/Views/SiteLayout.cshtml"; чтобы убедиться, что страница ошибки была стилизована правильно (как и остальная часть сайта) без дублирования макета/css включает.
~/Views/SiteLayout.cshtml было частично включено:~/Shared/LightboxLogin.cshtml который обеспечивает встроенный лайтбокс для входа.
~/Shared/LightboxLogin.cshtml еще частично для размещения фактическая форма входа: @Html.Partial("Login"), которая включает ~/Shared/Login.cshtml
Это используется для функций входа в систему на интерфейсе Сайта.
поскольку ошибка была вызвана в административной области сайта, контроллер был "Admin", и когда произошла ошибка,Error.cshtml был вызван, в который вошли SiteLayout.cshtml С HandleErrorInfo модель.
Это, в свою очередь, входит LightboxLogin, который затем включены частичные,Login... но в ~/Admin/Login.cshtml, который был включен .
этот вид на ~/Admin/Login.cshtml было так: @model Web.Models.Admin.Login
Итак, урок, извлеченный здесь, будьте осторожны с наименованием ваших партиалов, которые вы хотите включить. Если ~/Shared/Login.cshtml был ~/Shared/PublicLoginForm.cshtml и @Html.Partial("PublicLoginForm") было б тогда этой проблемы можно было бы избежать.
Sidenote: я исправил это так [как я не хотел реструктурировать мой просмотров]:
@if (!(Model is HandleErrorInfo))
{
@Html.Partial("LightboxLogin")
}
что означает, что частичное не включено, когда макет включен в условие ошибки.
У меня была эта ошибка со строго типизированными представлениями и исправила ее, также установив RouteData исходного контекста запроса.Значения ["controller"] и" action", чтобы соответствовать контроллеру страницы ошибок и именам действий.
Если вы посмотрите здесь, вы увидите расширенную реализацию HandleErrorAttribute, которая помимо поддержки JSON также показывает вам, что происходит в базовом классе с результатом вид.
https://www.dotnettricks.com/learn/mvc/exception-or-error-handling-and-logging-in-mvc4
Если конструкция ViewResult здесь похожа на логику, используемую Microsoft, то проблема может заключаться в том, что она может указать только новое (условие ошибки) представление, а не контроллер или действие (поскольку оно изменилось с исходного запроса). Возможно, именно поэтому фреймворк / обработчики MVC путаются с типизированными представлениями. Похоже, ошибка мне.
приведенный выше пример не включает это исправление, поэтому вам придется отредактировать его следующим образом (последние две строки и комментарий являются новыми):
var model = new HandleErrorInfo(httpError, controllerName, actionName);
filterContext.Result = new ViewResult
{
ViewName = View,
MasterName = Master,
ViewData = new ViewDataDictionary(model),
TempData = filterContext.Controller.TempData
};
// Correct routing data when required, e.g. to prevent error with typed views
filterContext.RouteData.Values["controller"] = "MyError"; // MyErrorController.Index(HandleErrorInfo)
filterContext.RouteData.Values["action"] = "Index";
Если вы не обрабатываете его в фильтре / атрибуте, вам нужно только сделать что-то вроде последних двух строк, где вы имеете дело с данными маршрутизации, например, многие примеры "OnError" создают контроллер ошибок, а затем вызывают IContoller.Выполнять. Но это уже другая история.
в любом случае, если вы получите эту ошибку, где бы вы ни находились обрабатывая ошибку, просто сбросьте исходное имя" контроллер "и" действие " на то, что вы используете, и это может исправить его для вас.