23

Voglio che tutti gli errori 401 siano reindirizzati a una pagina di errore personalizzata. Ho inizialmente impostato la seguente voce nel mio web.config.Come si visualizzano le pagine di errore personalizzate in Asp.Net Mvc 3?

<customErrors defaultRedirect="ErrorPage.aspx" mode="On"> 
    <error statusCode="401" redirect="~/Views/Shared/AccessDenied.aspx" /> 
</customErrors> 

Quando si utilizza IIS Express viene visualizzata la pagina di errore IIS Express 401 standard.

Nel caso in cui non utilizzi IIS Express viene restituita una pagina vuota. Utilizzando la scheda Rete di Google Chrome per verificare la risposta, vedo che mentre la pagina è vuota viene restituito uno stato 401 nelle intestazioni

Quello che ho provato fino ad ora è l'utilizzo di suggerimenti da this SO answer poiché sto usando IIS Express ma a no inutilmente. Ho provato a utilizzare una combinazione <custom errors> e <httpErrors> senza fortuna: l'errore standard o la pagina vuota sono ancora visualizzati.

La sezione httpErrors si presenta come questo al momento basata su the link dal above SO question (ho trovato anche un altro molto promising answer però senza fortuna - risposta vuota)

<system.webServer> 
    <httpErrors errorMode="DetailedLocalOnly" existingResponse="PassThrough" > 
    <remove statusCode="401" /> 
    <error statusCode="401" path="/Views/Shared/AccessDenied.htm" /> 
    </httpErrors> 

<!-- 
<httpErrors errorMode="Custom" 
      existingResponse="PassThrough" 
      defaultResponseMode="ExecuteURL"> 
     <remove statusCode="401" /> 
    <error statusCode="401" path="~/Views/Shared/AccessDenied.htm" 
     responseMode="File" /> 
</httpErrors> 
--> 
</system.webServer> 

ho anche modificato il file applicationhost.config e modificato <httpErrors lockAttributes="allowAbsolutePathsWhenDelegated,defaultPath"> a <httpErrors lockAttributes="allowAbsolutePathsWhenDelegated"> in base alle informazioni da iis.net. Durante il corso dei miei sforzi sono anche riuscito a incappare in questo errore come descritto in another SO question.

Come visualizzare pagine di errore personalizzate in Asp.Net Mvc 3?

Ulteriori informazioni

le seguenti azioni di controllo sono stati decorati con l'attributo Authorise per un utente specifico.

+0

Vorrei anche sapere come visualizzare gli errori personalizzati (nel mio caso un errore 403) - 500 errori funzionano bene ... –

+0

Creata una piccola libreria per semplificare la procedura. È disponibile: https://github.com/Buildstarted/Errlusion – Buildstarted

+1

Ho pensato che potresti essere interessato a vedere questo [post SO] (http://stackoverflow.com/questions/6308186/custom-errors-not-working-with -iisexpress) – CBRRacer

risposta

10

Non sono mai riuscito a ottenere CustomErrors in un web.config e MVC per giocare bene insieme, quindi ho rinunciato. Lo faccio invece.

In global.asax:

protected void Application_Error() 
    { 
     var exception = Server.GetLastError(); 
     var httpException = exception as HttpException; 
     Response.Clear(); 
     Server.ClearError(); 
     var routeData = new RouteData(); 
     routeData.Values["controller"] = "Errors"; 
     routeData.Values["action"] = "General"; 
     routeData.Values["exception"] = exception; 
     Response.StatusCode = 500; 
     if (httpException != null) 
     { 
      Response.StatusCode = httpException.GetHttpCode(); 
      switch (Response.StatusCode) 
      { 
       case 403: 
        routeData.Values["action"] = "Http403"; 
        break; 
       case 404: 
        routeData.Values["action"] = "Http404"; 
        break; 
      } 
     } 
     // Avoid IIS7 getting in the middle 
     Response.TrySkipIisCustomErrors = true; 
     IController errorsController = new GNB.LG.StrategicPlanning.Website.Controllers.ErrorsController(); 
     HttpContextWrapper wrapper = new HttpContextWrapper(Context); 
     var rc = new RequestContext(wrapper, routeData); 
     errorsController.Execute(rc); 
    } 

In ErrorsController:

public class ErrorsController 
{ 
    public ActionResult General(Exception exception) 
    { 
     // log the error here 
     return View(exception); 
    } 

    public ActionResult Http404() 
    { 
     return View("404"); 
    } 

    public ActionResult Http403() 
    { 
     return View("403"); 
    } 
} 

Nel web.config:

<customErrors mode="Off" /> 

che ha funzionato per me, non importa dove o come l'errore è creato. 401 non è gestito lì in questo momento, ma potresti aggiungerlo abbastanza facilmente.

+1

grazie per la risposta - tuttavia ho visto questo approccio e per qualche motivo non mi ha attratto. – Ahmad

+1

@Ahm non me nemmeno, ma funziona. :) Ho trovato il tentativo di configurarlo con CustomErrors in web.config che, a seconda di dove/come viene generato l'errore, non sempre funziona. – Tridus

+1

Ottima risposta - tranne che aggiungerei anche if (! HttpContext.Current.IsDebuggingEnabled) attorno al blocco in Application_Error in modo che gli errori continuino a essere visualizzati durante il debug. – NightOwl888

34

io uso questi passaggi:

// in Global.asax.cs: 
     protected void Application_Error(object sender, EventArgs e) { 

      var ex = Server.GetLastError().GetBaseException(); 

      Server.ClearError(); 
      var routeData = new RouteData(); 
      routeData.Values.Add("controller", "Error"); 
      routeData.Values.Add("action", "Index"); 

      if (ex.GetType() == typeof(HttpException)) { 
       var httpException = (HttpException)ex; 
       var code = httpException.GetHttpCode(); 
       routeData.Values.Add("status", code); 
      } else { 
       routeData.Values.Add("status", 500); 
      } 

      routeData.Values.Add("error", ex); 

      IController errorController = new Kavand.Web.Controllers.ErrorController(); 
      errorController.Execute(new RequestContext(new HttpContextWrapper(Context), routeData)); 
     } 

     protected void Application_EndRequest(object sender, EventArgs e) { 
      if (Context.Response.StatusCode == 401) { // this is important, because the 401 is not an error by default!!! 
       throw new HttpException(401, "You are not authorised"); 
      } 
     } 

E:

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

     public ActionResult Index(int status, Exception error) { 
      Response.StatusCode = status; 
      return View(status); 
     } 

     protected override void Dispose(bool disposing) { 
      base.Dispose(disposing); 
     } 
    } 

E vista indice nella cartella di errore:

@* in ~/Views/Error/Index.cshtml: *@ 

@model Int32  
@{ 
    Layout = null; 
}  
<!DOCTYPE html>  
<html> 
<head> 
    <title>Kavand | Error</title> 
</head> 
<body> 
    <div> 
     There was an error with your request. The error is:<br /> 
     <p style=" color: Red;"> 
     @switch (Model) { 
      case 401: { 
        <span>Your message goes here...</span> 
       } 
       break; 
      case 403: { 
        <span>Your message goes here...</span> 
       } 
       break; 
      case 404: { 
        <span>Your message goes here...</span> 
       } 
       break; 
      case 500: { 
        <span>Your message goes here...</span> 
       } 
       break; 
      //and more cases for more error-codes... 
      default: { 
        <span>Unknown error!!!</span> 
       } 
       break; 
     } 
     </p> 
    </div> 
</body> 
</html> 

E -Il passo finale:

<!-- in web.config: --> 

<customErrors mode="Off"/> 
+0

sembra funzionare, l'eccezione è fastidiosa durante il debug con Autenticazione di Windows e ho dovuto aggiungere httpErrors existingResponse = "PassThrough" alla configurazione web durante il test su un server. Grazie però ... –

+0

il suo errore di lancio CS0151: Un'espressione di commutazione o un'etichetta di caso deve essere un bool, un carattere, una stringa, un integrale, un enumerio o un tipo nullable corrispondente .. help plz ?? – codespider

+0

Questo funziona solo per me durante il debug. Come posso farlo funzionare sul server? Vedo ancora le pagine di errore predefinite sul server. IIS ha la modalità Impostazioni pagine di errore = Off. – Soenhay

9

Forse mi manca qualcosa, ma MVC ha un valore globale predefinito ErrorHandlerAttribute che utilizza errori personalizzati. Questo è spiegato abbastanza bene here.

public static void RegisterGlobalFilters(GlobalFilterCollection filters) 
{ 
    filters.Add(new HandleErrorAttribute()); 
} 

Tutto quello che dovete fare è accendere custom errors nella configurazione, e quindi l'errore di installazione personalizzato reindirizza, preferibilmente ad un HTML file statico (nel caso ci sia gli errori con l'applicazione).

<customErrors mode="On" defaultRedirect="errors.htm"> 
    <error statusCode="404" redirect="errors404.htm"/> 
</customErrors> 

Se si preferisce potrebbe anche puntare a un personalizzato Controller per visualizzare gli errori. Nell'esempio seguente ho appena utilizzato il routing predefinito su un Controller denominato Error, con un'azione denominata Index e un parametro stringa denominato id (per ricevere il codice di errore). Ovviamente potresti usare qualsiasi routing che desideri. Il tuo esempio non funziona perché stai cercando di collegarti direttamente alla directory Views senza passare per uno Controller. MVC .NET non invia direttamente richieste alla cartella Views.

<customErrors mode="On" defaultRedirect="/error/index/500"> 
    <error statusCode="404" redirect="/error/index/404"/> 
</customErrors> 

Il ErrorHandlerAttribute può essere utilizzato anche a lungo con Controllers/Actions per reindirizzare gli errori a nome Views relativi al Controller. Per esempio per mostrare la View nome MyArgumentError quando si verifica un'eccezione di tipo ArgumentException è possibile utilizzare:

[ControllerAction,ExceptionHandler("MyArgumentError",typeof(ArgumentException))] 
public void Index() 
{ 
    // some code that could throw ArgumentExcepton 
} 

Naturalmente un'altra opzione è quella di aggiornare la pagina magazzino Error in Shared.

+2

Il problema è che IIS Express gestisce già gli altri codici di stato (non i 500), quindi quello che stai suggerendo non sempre funziona (dipende dalla configurazione di IIS). IIS mostra solo la propria pagina e non ci arriva mai alla vista in asp. –

+0

È vero, questa è solo la configurazione di IIS, anche se è un altro problema. La gestione degli errori MVC dovrebbe essere eseguita come sopra. – TheCodeKing

0

Esaminando la prima parte del proprio web.config, si punta direttamente a una pagina .aspx. Quando ho impostato le mie pagine di errore, ho indicato direttamente un controller e un'azione. Ad esempio:

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

E ho avuto un controller di errore con tutte le azioni richieste. Non penso che MVC funzioni bene con le chiamate dirette alle pagine .aspx.

+0

Funziona con le pagine aspx, infatti se si utilizza la modalità di riscrittura, è necessario utilizzare file di contenuto statico (non azioni) –

Problemi correlati