32

I'm experiencing a rather frustrating problem. My MVC site runs fine for the most part, but randomly throws an error (which shows a friendly error to the user). When I check the logs, this is what I get:

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'.

Moments later, the same user could hit refresh and the page loads fine. I'm stuck. ;(

Update: added stack trace

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

4 回答 4

19

这是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与信息一起被抛出

传入字典的模型项是 type ,System.Web.Mvc.HandleErrorInfo但是这个字典需要一个 type 的模型项Igwt.Boh.Website.Web.Controllers.SiteViewData

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

IndexViewData在(and SiteViewData) 属性已经初始化之后,在操作中引发的任何异常都将发生的可能性非常大。

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

不会修复 - 请参阅评论。


“wontfix”提到的评论来自微软团队的一位前成员,以及他们对解决它的建议(粗体):

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

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

于 2010-01-04T06:18:33.540 回答
10

我处理该问题的解决方案是删除布局页面顶部的 @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>
}
于 2015-05-28T23:05:32.840 回答
4

我刚刚在我的应用程序中发现了一个类似的问题,并想为我描述修复方法。就我而言,我遇到了以下异常:

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必须Layout = "~/Views/SiteLayout.cshtml";确保错误页面的样式正确(就像网站的其他部分一样),而不复制布局/css 包含。

~/Views/SiteLayout.cshtml有一个部分包括:~/Shared/LightboxLogin.cshtml它为登录提供了一个内联灯箱。 ~/Shared/LightboxLogin.cshtml进一步部分嵌入了实际的登录表单:@Html.Partial("Login")其中包括~/Shared/Login.cshtml 这用于网站前端的登录功能。

因为错误是在站点的管理区域引起的,所以控制器是“管理员”,当发生错误时,Error.cshtml会调用它,它包含SiteLayout.cshtmlHandleErrorInfo模型中。这又包括LightboxLogin,然后包括部分,Login......但是还有另一个视图~/Admin/Login.cshtml被包含在内@Html.Partial("Login")

这个观点~/Admin/Login.cshtml有这个:@model Web.Models.Admin.Login

所以,这里学到的教训是要小心你想要包含的部分的命名。如果~/Shared/Login.cshtml曾经~/Shared/PublicLoginForm.cshtml@Html.Partial("PublicLoginForm")被使用过,那么这个问题就可以避免了。

旁注:我这样解决了这个问题[因为我不想重组我的观点]:

@if (!(Model is HandleErrorInfo))
{
   @Html.Partial("LightboxLogin")
}

这意味着当布局包含在错误条件中时,不包含 Partial。

于 2014-12-11T20:47:11.840 回答
1

我在强类型视图中遇到了这个错误,并通过设置原始请求上下文的 RouteData.Values["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.Execute。但那是另一回事了。

无论如何,如果您收到此错误,无论您在哪里处理错误,只需将原始“控制器”和“操作”名称重置为您正在使用的任何名称,它也可以为您修复它。

于 2013-10-17T15:17:10.440 回答