かなりイライラする問題が発生しています。私のMVCサイトは大部分は問題なく動作しますが、ランダムにエラーをスローします(ユーザーにわかりやすいエラーが表示されます)。ログを確認すると、次のようになります。
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'.
しばらくすると、同じユーザーが更新を押してページが正常に読み込まれます。行き詰まっています。 ;(
更新:追加されたスタックトレース
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)
ここ は 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
に情報がスローされますディクショナリに渡されたモデルアイテムのタイプは
System.Web.Mvc.HandleErrorInfo
ですが、このディクショナリにはタイプIgwt.Boh.Website.Web.Controllers.SiteViewData
のモデルアイテムが必要です。新しい
ErrorData
プロパティをViewResult
クラスに追加して、代わりにHandleErrorInfo
クラスのインスタンスを格納することは可能ですか?このようにして、ViewData
は変更されません。アクションでスローされる例外は、
IndexViewData
(およびSiteViewData
)プロパティがすでに初期化された後に発生する可能性がかなり高いです。2010年1月27日午前12:24に閉鎖
修正されません-コメントを参照してください。
「wontfix」で言及されたコメントは、Microsoftチームの元メンバーからのものであり、それを回避するための提案(太字)が含まれています。
[HandleError]属性が実行されるまでに、元のActionResultオブジェクトへの参照が失われています。とにかくビューを表示するつもりだったかどうかはわかりません。おそらくリダイレクトするつもりでした。コントローラーからビューにモデルを渡す役割を果たしていたパイプラインの一部(ViewResult)はなくなりました。
例外が発生した場合、アプリケーションが機能していたモデルは、おそらく破損しているか、使用不可として扱われるはずです。 ベストプラクティスは、エラービューとその依存関係(マスターページなど)の両方が元のモデルを必要としないようにエラービューを作成することです
この問題に対処するための私の解決策は、レイアウトページの上部にある@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>
}
私は自分のアプリで同様の問題を追跡し、修正を説明したいと思います。私の場合、次の例外が発生しました。
_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.cshtml
_とHandleErrorInfo
モデルが含まれていました。次に、これにはLightboxLogin
が含まれ、次に部分的なLogin
...が含まれますbut@Html.Partial("Login")
に含まれる別のビューが_~/Admin/Login.cshtml
_にありました代わりに。
_~/Admin/Login.cshtml
_のこのビューには、_@model Web.Models.Admin.Login
_がありました。
したがって、ここで学んだ教訓は、含めるパーシャルの命名に注意することです。 _~/Shared/Login.cshtml
_が_~/Shared/PublicLoginForm.cshtml
_であり、@Html.Partial("PublicLoginForm")
が使用された場合、この問題は回避されたはずです。
サイドノート:これを次のように修正しました[ビューを再構築したくなかったため]:
_@if (!(Model is HandleErrorInfo))
{
@Html.Partial("LightboxLogin")
}
_
つまり、レイアウトがエラー条件に含まれている場合、パーシャルは含まれません。
厳密に型指定されたビューでこのエラーが発生し、元のリクエストコンテキストのRouteData.Values ["controller"]と "action"をエラーページコントローラーとアクション名に一致するように設定することで修正しました。
ここを見ると、JSONサポートに加えて、拡張されたHandleErrorAttribute実装が表示され、結果ビューを使用して基本クラスで何が行われているかがわかります。
https://www.dotnettricks.com/learn/mvc/exception-or-error-handling-and-logging-in-mvc4
ここでのViewResultの構築がMicrosoftで使用されているロジックのようなものである場合、問題はコントローラー(または元の要求から変更されているため)ではなく、新しい(エラー状態)ビューしか指定できないことです。おそらくそれが、MVCフレームワーク/ハンドラーが型付きビューと混同されている理由です。私にはバグのようです。
上記の例にはこの修正が含まれていないため、次のように編集する必要があります(最後の2行とコメントは新しい)。
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";
フィルター/属性でそれを処理しない場合は、ルーティングデータを処理する最後の2行のようなものを実行するだけで済みます。 「OnError」の例の多くは、エラーコントローラーを作成してからIContoller.Executeを呼び出します。しかし、それは別の話です。
とにかく、このエラーが発生した場合は、どこでエラーを処理していても、元の「コントローラー」と「アクション」の名前を使用している名前にリセットするだけで修正されます。