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)
Here is an issue on codeplex explaining why that error occurs.
Quote from http://web.archive.org/web/20131004122626/http://aspnet.codeplex.com/workitem/1795 since original link is dead:
HandleError Attribute should not store exception information in ViewData
When the
HandleError
attribute handles an exception, it stores the exception information in theViewData
. This is a problem when theError.aspx
inherits from thesite.master
and thesite.master
class is declared as follows.public partial class Site : System.Web.Mvc.ViewMasterPage<SiteViewData> { }
SiteViewData
contains:public class SiteViewData { public String Title { get; set; } }
Each page
ViewData
class inherits from theSiteViewData
class and looks something like thispublic class IndexViewData : SiteViewData { public String Message { get; set; } public String SupportedLanguages {get; set;} }
This approach allows one to write code in the
Site.Master
page as follows<title><%= Html.Encode(ViewData.Model.Title) %></title>
Unfortunately, when an exception is thrown, the model has been replaced with an instance of the
HandleErrorInfo
class. This causes anInvalidOperationException
to be thrown with the informationThe model item passed into the dictionary is of type
System.Web.Mvc.HandleErrorInfo
but this dictionary requires a model item of typeIgwt.Boh.Website.Web.Controllers.SiteViewData
.Is it possible for a new
ErrorData
property to be added to theViewResult
class to store the instance of theHandleErrorInfo
class instead? This way theViewData
does not get changed.Chances are pretty good that any exception thrown in the action will occur after the
IndexViewData
(andSiteViewData
) properties have already been initialized.Closed Jan 27, 2010 at 12:24 AM by
Won't fix - see comments.
The comments mentioned with "wontfix" are from a former member of the Microsoft team, along with their suggestion for working around it (bolded):
By the time the [HandleError] attribute executes, we've lost the reference to the original ActionResult object. We don't even know if you intended to show a view anyway - maybe you intended to redirect. The part of the pipeline (the ViewResult) that would have been responsible for passing the model from the controller to the view is gone.
If an exception occurs, any model the application was working on should probably be treated as corrupt or unavailable anyway. The best practice would be to write your Error view such that neither it nor its dependencies (such as its master page) requires the original model.