哎呀!为什么System.Web.Mvc.HandleErrorInfo会传递给我的视图?

Cha*_*eus 28 c# asp.net-mvc viewdata controller views

我遇到了一个相当令人沮丧的问题.我的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'.
Run Code Online (Sandbox Code Playgroud)

片刻之后,同一个用户可以点击刷新并且页面加载正常.我被卡住了.(

更新:添加堆栈跟踪

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)
Run Code Online (Sandbox Code Playgroud)

Çağ*_*kin 17

codeplex上的一个问题,解释了为什么会发生错误.

引自http://web.archive.org/web/20131004122626/http://aspnet.codeplex.com/workitem/1795,因为原始链接已死:

HandleError属性不应在ViewData中存储异常信息

HandleError属性处理异常时,它将异常信息存储在ViewData.当Error.aspxsite.mastersite.master类的继承声明如下时,这是一个问题.

public partial class Site : System.Web.Mvc.ViewMasterPage<SiteViewData>
{
}
Run Code Online (Sandbox Code Playgroud)

SiteViewData 包含:

public class SiteViewData 
{
  public String Title { get; set; } 
}
Run Code Online (Sandbox Code Playgroud)

每个页面ViewData类都继承自SiteViewData类,看起来像这样

public class IndexViewData : SiteViewData
{
  public String Message { get; set; }
  public String SupportedLanguages {get; set;}
}
Run Code Online (Sandbox Code Playgroud)

这种方法允许用户在Site.Master页面中编写代码如下

<title><%= Html.Encode(ViewData.Model.Title) %></title>
Run Code Online (Sandbox Code Playgroud)

不幸的是,当抛出异常时,模型已被替换为HandleErrorInfo类的实例.这会导致InvalidOperationException信息被抛出

传递到字典中的模型项是类型的,System.Web.Mvc.HandleErrorInfo但此字典需要类型的模型项Igwt.Boh.Website.Web.Controllers.SiteViewData.

是否可以将新ErrorData属性添加到ViewResult类中以存储类的实例HandleErrorInfo?这样ViewData就不会改变.

IndexViewData(和SiteViewData)属性已经初始化之后,动作中抛出的任何异常都很有可能.

关闭2010年1月27日上午12:24 by

无法修复 - 请参阅评论.


"wontfix"中提到的评论来自微软团队的前成员,以及他们为解决它而提出的建议(加粗):

到[HandleError]属性执行时,我们已经丢失了对原始ActionResult对象的引用.我们甚至不知道您是否打算显示视图 - 也许您打算重定向.管道的一部分(ViewResult)负责将模型从控制器传递到视图.

如果发生异常,应用程序正在处理的任何模型都应该被视为已损坏或无法使用.最佳做法是编写错误视图,使其及其依赖关系(例如其母版页)都不需要原始模型.

  • 你钉了它......我正在深入研究它,我认为我正在找到问题是从需要<BaseViewData>的网站母版页导出的错误页面.至少它是一个简单的修复,我只是为我的错误页面制作一个新的母版页来源自.谢谢! (3认同)

Gav*_*vin 8

我解决这个问题的方法是删除布局页面顶部的@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>
}
Run Code Online (Sandbox Code Playgroud)