2010-01-04 21 views
22

Estoy experimentando un problema bastante frustrante. Mi sitio MVC funciona bien en su mayor parte, pero arroja al azar un error (que muestra un error amistoso para el usuario). Cuando compruebo los registros, esto es lo que me sale:Argh! ¿Por qué System.Web.Mvc.HandleErrorInfo se pasa a mis vistas?

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

Momentos más tarde, el mismo usuario podría golpear actualización y la página se carga bien. Estoy atascado. ; (

Actualización: añadido seguimiento de la pila

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) 

Respuesta

14

Here es una cuestión sobre codeplex explicar por qué se produce ese error

Presupuesto de http://web.archive.org/web/20131004122626/http://aspnet.codeplex.com/workitem/1795 desde la fuente original está muerto:

.

HandleError El atributo no debe almacenarse e información de excepción en ViewData

Cuando el atributo HandleError maneja una excepción, almacena la información de excepción en el ViewData. Esto es un problema cuando el Error.aspx hereda de site.master y la clase site.master se declara de la siguiente manera.

public partial class Site : System.Web.Mvc.ViewMasterPage<SiteViewData> 
{ 
} 

SiteViewData contiene:

public class SiteViewData 
{ 
    public String Title { get; set; } 
} 

Cada página ViewData clase hereda de la clase SiteViewData y se ve algo como esto

public class IndexViewData : SiteViewData 
{ 
    public String Message { get; set; } 
    public String SupportedLanguages {get; set;} 
} 

Este enfoque permite escribir código en la página Site.Master como sigue

<title><%= Html.Encode(ViewData.Model.Title) %></title> 

Desafortunadamente, cuando se lanza una excepción, el modelo ha sido reemplazado por una instancia de la clase HandleErrorInfo. Esto provoca un InvalidOperationException ser arrojado con la información

El elemento de modelo pasado en el diccionario es de tipo System.Web.Mvc.HandleErrorInfo pero este diccionario requiere un elemento de modelo de tipo Igwt.Boh.Website.Web.Controllers.SiteViewData.

¿Es posible agregar una nueva propiedad ErrorData a la clase ViewResult para almacenar la instancia de la clase HandleErrorInfo? De esta forma, el ViewData no cambia.

Las posibilidades son bastante buenas de que cualquier excepción lanzada en la acción se produzca después de que las propiedades IndexViewData (y SiteViewData) ya se hayan inicializado.

cerrado Ene 27 de 2010 a 12:24a.m. por

No fijará - ver los comentarios.


Los comentarios mencionados con "wontfix" son de un ex miembro del equipo de Microsoft, junto con su sugerencia para trabajar alrededor de ella (en negrita):

En el momento en el [HandleError ] atributo se ejecuta, hemos perdido la referencia al objeto ActionResult original. Ni siquiera sabemos si tenía la intención de mostrar una vista de todos modos, tal vez tenía la intención de redirigir. La parte de la canalización (ViewResult) que hubiera sido responsable de pasar el modelo del controlador a la vista se ha ido .

Si se produce una excepción, cualquier modelo que la aplicación estaba trabajando en probablemente debería tratarse como corrupto o no disponible de todos modos. La mejor práctica de sería escribir su vista de Error de manera que ni ella ni sus dependencias (como su página maestra) requieren el modelo original .

+3

clavasteis ... Yo estaba cavando en ella un poco y creo que estaba en el camino correcto para constatar que el problema estaba en las páginas de error derivadas de la página maestra del sitio que requiere . Al menos es una solución fácil, crearé una nueva página maestra para que deriven mis páginas de error. Gracias! – Chaddeus

+0

De nada :) –

+0

Hola çağdaş No somos capaces de comprender e implementar la solución dada anteriormente. ¿Puede explicar más sobre cómo implementar la solución? El elemento de modelo que se pasa al diccionario es del tipo 'System.Web.Mvc.HandleErrorInfo', pero este diccionario requiere un elemento de modelo del tipo 'MAQ.Host.Models.ErrorModel'. en System.Web.Mvc.ViewDataDictionary'1.SetModel (Valor del objeto) en System.Web.Mvc.ViewDataDictionary..ctor (Diccionario ViewDataDictionary) en MAQ.Host.EntityLayer.ViewBasePage'1.SetViewData (ViewDataDictionary viewData) en –

1

tuve este error con vistas al establecimiento inflexible y lo arreglaron por el establecimiento también RouteData.Values ​​del contexto de la petición en el que [] "controlador" y "acción" para que coincida con el controlador y acción nombres de las páginas de error.

Si mira aquí, verá una implementación mejorada HandleErrorAttribute que, además del soporte JSON, también le muestra lo que está sucediendo en la clase base con la vista de resultados.

http://www.dotnet-tricks.com/Tutorial/mvc/19D9140313-Exception-or-Error-Handling-and-Logging-in-MVC4.html

Si la construcción ViewResult aquí es algo parecido a la lógica utilizada por Microsoft, entonces el problema podría ser que sólo es capaz de especificar una nueva vista (estado de error), no el controlador o acción (como se ha cambiado desde la solicitud original). Tal vez esa es la razón por la cual los manejadores/framework MVC se confunden con vistas tipadas. Me parece un error.

El ejemplo anterior no incluye esta revisión, por lo que tendrá que editar la siguiente manera (las dos últimas líneas y comentarios son nuevos):

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"; 

Si usted no está manejando en un filtro/attribute, entonces solo necesita hacer algo como las últimas dos líneas en las que trata los datos de enrutamiento, por ejemplo muchos ejemplos de "OnError" construyen un controlador de error y luego llaman a IContoller.Execute. Pero esa es otra historia.

De todos modos, si obtiene este error, donde sea que esté manejando el error, solo reinicie el nombre del "controlador" original y el nombre de "acción" a lo que esté utilizando y también puede solucionarlo.

2

Acabo de rastrear un problema similar en mi aplicación y quería describir la solución para mí. En mi caso, me estaba poniendo la siguiente excepción:

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

Y yo estaba usando [HandleError] a errores de ruta a ~/Shared/Error.cshtml

¿Qué pasó [al menos en mi caso] era: ~/Shared/Error.cshtml tenía Layout = "~/Views/SiteLayout.cshtml"; para asegurarse de que la página de Error se diseñó correctamente (como el resto del sitio) sin duplicar el diseño/incluye css.

~/Views/SiteLayout.cshtml tenía un parcial incluido: ~/Shared/LightboxLogin.cshtml que proporciona un lightbox en línea para el inicio de sesión. ~/Shared/LightboxLogin.cshtml tenían un parcial adicional para incrustar la forma real entrada: @Html.Partial("Login") que incluye ~/Shared/Login.cshtml Esto se utiliza para la funcionalidad de inicio de sesión en el front-end del sitio.

Como el error se produjo en el área de administración del sitio, el controlador era "Admin" y cuando se produjo un error, se invocó Error.cshtml, que incluía SiteLayout.cshtml con un modelo HandleErrorInfo. Esto a su vez incluye LightboxLogin, que a su vez incluye el parcial, pero Login ... había otra vista en ~/Admin/Login.cshtml que fue incluido por el @Html.Partial("Login") lugar.

Esta vista ~/Admin/Login.cshtml tenían esto: @model Web.Models.Admin.Login

Así, lección aprendida aquí es tener cuidado de su nombramiento de sus parciales que desee incluir. Si se usó ~/Shared/Login.cshtml~/Shared/PublicLoginForm.cshtml y @Html.Partial("PublicLoginForm"), entonces este problema se habría evitado.

Nota al margen: Me corrigió esta situación como tal [como yo no quería reestructurar mis puntos de vista]:

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

que significa que el parcial no se incluye cuando la disposición se incluye en una condición de error.

6

Mi solución para tratar con el problema es eliminar la directiva @Model en la parte superior de la página de diseño y luego hacer algunas comprobaciones en las que normalmente esperaría ver mi modelo para cambiar entre los diferentes modelos que podrían conseguir pasado en por ejemplo

@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> 
} 
Cuestiones relacionadas