2014-07-24 15 views
7

Piszę aplikację ASP.NET MVC i napotkałem następujący problem. Chcę utworzyć niestandardowe strony błędów zawierające szczegółowe informacje o błędach (takie jak komunikat o błędzie lub sterownik spowodował błąd), ale nie mogę udostępnić modelu w widoku za pomocą obiektu HandleErrorInfo.Jak mogę udostępnić model HandleErrorInfo obiektom?

Początkowo skonfigurowany plik Web.config do obsługi niestandardowych błędów:

<customErrors mode="On" defaultRedirect="~/Error"> 
    <error statusCode="404" redirect="~/Error/NotFound"/> 
</customErrors> 

Potem stworzył błąd kontrolera zarządzania widoki błędach:

public class ErrorController : Controller 
{ 
    public ActionResult Index() 
    { 
     return View("Error"); 
    } 

    public ViewResult NotFound() 
    { 
     Response.StatusCode = 404; 
     return View("NotFound"); 
    } 
} 

I na Widoku I dodanych Typ modelu:

@model System.Web.Mvc.HandleErrorInfo 

Ale model jest nieważny za każdym razem i nie wiem, jak przejść prawo obiekt z informacjami o błędach do widoku i gdzie ten obiekt powinien zostać utworzony. Możesz mi pomóc? Czy można to zrobić w ten sposób?

Odpowiedz

12

Masz tu do czynienia z dwiema różnymi "warstwami". <customErrors> jest poza głównym środowiskiem ASP.NET. Następnie HandleError jest poza szkieletem MVC. Podczas korzystania z <customErrors> program ASP.NET nie jest świadomy, jak przekazać informacje o wyjątku do widoku, po prostu załaduje/przekieruje użytkownika do strony błędu.

Aby widok działał, musisz zachować wszystko w ekosystemie MVC. Musisz więc użyć HandleErrorAttribute lub innego. You can see in the source code of the attribute próbuje wykryć, kiedy wystąpił nieobsługiwany wyjątek, a jeśli włączono błędy niestandardowe, następnie obraca nowe ViewResult instancją HandleErrorInfo, która zawiera informacje o wyjątku.

Należy zauważyć, że w domyślnym projekcie MVC HandleErrorAttribute jest stosowany jako filtr globalny w pliku App_Start/FilterConfig.cs.

+0

Dzięki, wszystko działa teraz prawidłowo. –

+0

Bardzo przydatne, wszystko, czego mi brakowało, to filtr, z jakiegoś powodu skomentowałem to. dzięki! – Alex

+1

Mam taką samą konfigurację jak @Roman, ale nadal stoję w obliczu HandleErrorInfo mającym wartość null w widoku błędu. Mam zarejestrowany filtr i również [HandleError] na kontrolerach. czy ktoś może rzucić trochę światła. –

1

ta nie działa dla mnie, ale zainspirował mnie do stwierdzenia, że ​​mój Global.asax.Application_Start() nie zarejestrował klasa FilterConfig tak:

FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 

To, w połączeniu z odpowiedzią Steven V za rozwiązany mój model zerowy problem.

5

Znalazłem inny sposób. Przesyłanie modelu błędu do wyświetlenia z kontrolera.

1. Global.asax

protected void Application_Error(object sender, EventArgs e) 
{ 
    var httpContext = ((MvcApplication)sender).Context; 
    var currentController = " "; 
    var currentAction = " "; 
    var currentRouteData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(httpContext)); 

    if (currentRouteData != null) 
    { 
     if (currentRouteData.Values["controller"] != null && !String.IsNullOrEmpty(currentRouteData.Values["controller"].ToString())) 
     { 
      currentController = currentRouteData.Values["controller"].ToString(); 
     } 

     if (currentRouteData.Values["action"] != null && !String.IsNullOrEmpty(currentRouteData.Values["action"].ToString())) 
     { 
      currentAction = currentRouteData.Values["action"].ToString(); 
     } 
    } 

    var ex = Server.GetLastError(); 
    //var controller = new ErrorController(); 
    var routeData = new RouteData(); 
    var action = "GenericError"; 

    if (ex is HttpException) 
    { 
     var httpEx = ex as HttpException; 

     switch (httpEx.GetHttpCode()) 
     { 
      case 404: 
       action = "NotFound"; 
       break; 

      // others if any 
     } 
    } 

    httpContext.ClearError(); 
    httpContext.Response.Clear(); 
    httpContext.Response.StatusCode = ex is HttpException ? ((HttpException)ex).GetHttpCode() : 500; 
    httpContext.Response.TrySkipIisCustomErrors = true; 

    routeData.Values["controller"] = "Error"; 
    routeData.Values["action"] = action; 
    routeData.Values["exception"] = new HandleErrorInfo(ex, currentController, currentAction); 

    IController errormanagerController = new ErrorController(); 
    HttpContextWrapper wrapper = new HttpContextWrapper(httpContext); 
    var rc = new RequestContext(wrapper, routeData); 
    errormanagerController.Execute(rc); 
} 

2. Błąd kontrolera:

public class ErrorController : Controller 
{ 
    // 
    // GET: /Error/ 

    public ActionResult Index() 
    { 
     return RedirectToAction("GenericError", new HandleErrorInfo(new HttpException(403, "Dont allow access the error pages"), "ErrorController", "Index")); 
    } 

    public ViewResult GenericError(HandleErrorInfo exception) 
    {    
     return View("Error", exception); 
    } 

    public ViewResult NotFound(HandleErrorInfo exception) 
    {   
     ViewBag.Title = "Page Not Found"; 
     return View("Error", exception); 
    }   
} 

3. Widok/Shared/Error.cshtml:

@model System.Web.Mvc.HandleErrorInfo 
@{ 
    ViewBag.Title = ViewBag.Title ?? "Internal Server Error"; 
} 
<div class="list-header clearfix"> 
    <span>Error : @ViewBag.Title</span> 
</div> 
<div class="list-sfs-holder"> 
    <div class="alert alert-error"> 
     An unexpected error has occurred. Please contact the system administrator. 
    </div> 
    @if (Model != null && HttpContext.Current.IsDebuggingEnabled) 
    { 
     <div> 
      <p> 
       <b>Exception:</b> @Model.Exception.Message<br /> 
       <b>Controller:</b> @Model.ControllerName<br /> 
       <b>Action:</b> @Model.ActionName 
      </p> 
      <div style="overflow: scroll"> 
       <pre> 
        @Model.Exception.StackTrace 
       </pre> 
      </div> 
     </div> 
    } 
</div> 

4. web.config:

<system.web> 
    <customErrors mode="Off" /> 
</system.web> 

Credits:https://thatsimpleidea.wordpress.com/2013/10/28/mvc-error-page-implementation/#comment-166

Powiązane problemy