Argh! ¿Por qué el Sistema.Web.Mvc.HandleErrorInfo se pasa a mis puntos de vista?


Estoy experimentando un problema bastante frustrante. Mi sitio MVC funciona bien en su mayor parte, pero arroja un error al azar (que muestra un error amigable al usuario). Cuando reviso los registros, esto es lo que obtengo:

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 pulsar actualizar y la página se carga bien. Estoy atascado. ;(

Actualización: añadido seguimiento de 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)
Author: Chaddeus, 2010-01-04

4 answers

Aquí hay un problema en codeplex explicando por qué ocurre ese error.

Cita de http://web.archive.org/web/20131004122626/http://aspnet.codeplex.com/workitem/1795 desde que el enlace original está muerto:

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

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

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

SiteViewData contiene:

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

Cada clase page ViewData 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 de la siguiente manera

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

Desafortunadamente, cuando se lanza una excepción, el modelo ha sido reemplazado con una instancia de la clase HandleErrorInfo. Esto hace que un InvalidOperationException sea lanzado con la información

El elemento modelo pasado al diccionario es de tipo System.Web.Mvc.HandleErrorInfo pero este diccionario requiere un elemento 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 en su lugar? De esta manera el ViewData no se cambia.

Es bastante probable que cualquier excepción lanzada en la acción ocurra después de que las propiedades IndexViewData (y SiteViewData) ya se hayan inicializado.

Cerrado ene 27, 2010 en 12: 24 AM por

No se soluciona-ver comentarios.


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

En el momento en que se ejecuta el atributo [HandleError], hemos perdido referencia al objeto original ActionResult. Ni siquiera sabemos si se pretende mostrar una visión de todos modos - tal vez la intención de redirigir. La parte de la tubería (el resultado de la vista) que habría sido responsable de pasar el modelo desde el controlador a la vista es ido.

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

 15
Author: Çağdaş Tekin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-07 10:59:19

Mi solución para lidiar con el problema es eliminar la directiva @model en la parte superior de la página de diseño y luego hacer algunas comprobaciones donde normalmente esperaría ver que mi modelo cambie entre los diferentes modelos que podrían pasarse, 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>
}
 6
Author: Gavin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-28 23:11:41

Acabo de rastrear un problema similar en mi aplicación y quería describir la solución para mí. En mi caso, estaba recibiendo 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] para enrutar errores a ~/Shared/Error.cshtml

Lo que sucedió [al menos en mi caso] fue: ~/Shared/Error.cshtml tenía Layout = "~/Views/SiteLayout.cshtml"; para asegurarse de que la página de error tuviera un estilo correcto (como el resto del sitio) sin duplicar el layout/css includes.

~/Views/SiteLayout.cshtml tenía un parcial incluido: ~/Shared/LightboxLogin.cshtml que proporciona un caja de luz en línea para el inicio de sesión. ~/Shared/LightboxLogin.cshtml tenía un parcial adicional para incrustar el formulario de inicio de sesión real: @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.

Debido a que el error se causó en el área de Administración del sitio, el controlador fue "Admin" y cuando se produjo un error, se invocó Error.cshtml, que incluía SiteLayout.cshtml con un modelo HandleErrorInfo. Esto a su vez incluía LightboxLogin, que luego incluía el Parcial, Login... pero había otro punto de vista en ~/Admin/Login.cshtml que fue incluido por el @Html.Partial("Login") en su lugar.

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

Por lo tanto, la lección aprendida aquí es tener cuidado con el nombre de sus parciales que desea incluir. Si ~/Shared/Login.cshtml fue ~/Shared/PublicLoginForm.cshtml y @Html.Partial("PublicLoginForm") se utilizó entonces este problema se habría evitado.

Nota al margen: Arreglé esto así [ya que no quería reestructurar mis puntos de vista]:

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

Lo que significa que el Parcial no se incluye cuando el diseño se incluye en una condición de error.

 3
Author: agrath,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-11 20:47:11

Tuve este error con vistas fuertemente mecanografiadas y lo arreglé estableciendo también RouteData del contexto de la solicitud original.Valores ["controlador"] y" acción " para que coincida con el controlador de página de error y los nombres de acción.

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

Https://www.dotnettricks.com/learn/mvc/exception-or-error-handling-and-logging-in-mvc4

Si la construcción ViewResult aquí se parece a la lógica utilizada por Microsoft, entonces el problema podría ser que solo puede especificar una nueva vista (condición de error), no el controlador o la acción (ya que ha cambiado desde la solicitud original). Tal vez es por eso que el framework MVC/handlers se están confundiendo con vistas escritas. Me parece un bicho.

El el ejemplo anterior NO incluye esta corrección, por lo que tendrá que editarla de la siguiente manera (las dos últimas líneas y el comentario 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 no lo está manejando en un filtro/atributo, solo necesita hacer algo como las dos últimas líneas donde está tratando con los datos de enrutamiento, por ejemplo, muchos ejemplos "OnError" construyen un controlador de errores y luego llaman a IContoller.Ejecutar. Pero esa es otra historia.

De todos modos, si obtiene este error, dondequiera que esté manejando el error, simplemente reinicie el nombre original de "controlador" y "acción" a lo que esté utilizando y puede arreglarlo para usted también.

 1
Author: Tony Wall,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-12 10:42:30