Аргх! Почему система.Сеть.В 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.Выполнять. Но это уже другая история.
в любом случае, если вы получите эту ошибку, где бы вы ни находились обрабатывая ошибку, просто сбросьте исходное имя" контроллер "и" действие " на то, что вы используете, и это может исправить его для вас.