net mvc how from example data asp c# asp.net-mvc controller views viewdata

mvc - viewdata c#



Argh! ¿Por qué System.Web.Mvc.HandleErrorInfo se pasa a mis vistas? (4)

Acabo de localizar 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 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 se diseñó correctamente (como el resto del sitio) sin duplicar el diseño / css incluido.

~/Views/SiteLayout.cshtml tenía un parcial incluido: ~/Shared/LightboxLogin.cshtml que proporciona una caja de luz en línea para el inicio de sesión. ~/Shared/LightboxLogin.cshtml tuvo un parcial adicional para incrustar el formulario de inicio de sesión real: @Html.Partial("Login") que incluye ~/Shared/Login.cshtml Esto se usa para la funcionalidad de inicio de sesión en el extremo frontal de sitio.

Debido a que 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 . A su vez, esto incluía LightboxLogin , que luego incluía Parcial, Login ... pero había otra vista en ~/Admin/Login.cshtml que fue incluida por @Html.Partial("Login") 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 al nombrar los parciales que desea incluir. Si se ~/Shared/Login.cshtml ~/Shared/PublicLoginForm.cshtml y se ~/Shared/PublicLoginForm.cshtml @Html.Partial("PublicLoginForm") entonces se habría evitado este problema.

Nota al margen: Arreglé esto así como [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.

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 amistoso para el 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 presionar actualizar y la página se carga bien. Estoy atascado. ;

Actualización: agregado de 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)


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 verificaciones donde normalmente esperaría ver mi modelo para cambiar 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> }


Tuve este error con vistas fuertemente tipadas y lo arreglé también configurando RouteData.Values ​​["controlador"] y "acción" del contexto de solicitud original para que coincidan con los nombres de acción y controlador de la página de error.

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

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

Si la construcción de ViewResult aquí es similar a la lógica utilizada por Microsoft, 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). Quizás es por eso que el framework / manejadores MVC se confunden con las vistas escritas. Me parece un error.

El ejemplo anterior NO incluye esta corrección, por lo que tendrá que editarlo de la siguiente manera (las últimas dos 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, entonces solo necesita hacer algo como las dos últimas líneas en las que está tratando con 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 obtienes este error, donde sea que estés manejando el error, simplemente restablece el nombre del "controlador" y la "acción" originales a lo que estés usando y también puede solucionarlo por ti.


Here hay un problema en Codeplex que explica por qué ocurre ese error.

Cita de http://web.archive.org/web/20131004122626/http://aspnet.codeplex.com/workitem/1795 ya 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 ViewData . Este es un problema cuando 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 clase ViewData página se hereda de la clase SiteViewData y se parece a esto

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

Este enfoque le permite a uno escribir código en la página de Site.Master siguiente manera

<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 hace que se InvalidOperationException una InvalidOperationException con la información

El elemento del modelo que se pasó al diccionario es de tipo System.Web.Mvc.HandleErrorInfo pero este diccionario requiere un elemento del modelo de tipo Igwt.Boh.Website.Web.Controllers.SiteViewData .

¿Es posible que se ErrorData una nueva propiedad ErrorData a la clase ViewResult para almacenar la instancia de la clase HandleErrorInfo ? De esta manera el ViewData no se modifica.

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

Cerrado el 27 de enero de 2010 a las 12:24 a.m. por

No solucionará - ver comentarios.

Los comentarios mencionados con "wontfix" son de un antiguo miembro del equipo de Microsoft, junto con su sugerencia para trabajar en torno a ellos (en negrita):

Cuando se ejecuta el atributo [HandleError], hemos perdido la referencia al objeto ActionResult original. Ni siquiera sabemos si pretendía mostrar una vista de todos modos, tal vez pretendía redirigir. La parte de la canalización (el ViewResult) que habría sido responsable de pasar el modelo del controlador a la vista ya no existe.

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