it-swarm.com.de

Benutzerdefinierte ASP.NET MVC 5-Fehlerseite

Ich verwende ein benutzerdefiniertes Berechtigungsattribut in einer ASP.NET MVC 5 -Anwendung wie folgt:

public class CustomAuthorizeAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext context)
    {
        if (context.HttpContext.Request.IsAuthenticated)
        {
            context.Result = new System.Web.Mvc.HttpStatusCodeResult((int)System.Net.HttpStatusCode.Forbidden);                
        }
        else
        {
            base.HandleUnauthorizedRequest(context);
        }
    }
}

Im system.web Abschnitt meiner web.config Ich erwähnte Fehlerpfade wie:

<system.web>
    <customErrors mode="On" defaultRedirect="/Error/Error">
      <error statusCode="403" redirect="/Error/NoPermissions"/>
    </customErrors>
</system.web>

Ich werde jedoch niemals zu meiner benutzerdefinierten Fehlerseite umgeleitet unter /Error/NoPermissions. Stattdessen zeigt der Browser die allgemeine Fehlerseite "HTTP Error 403.0 - Forbidden" an.

29
Haider

Vielen Dank an alle, aber das Problem ist nicht mit 403-Code. Eigentlich lag das Problem an der Art und Weise, wie ich versucht habe, 403 zurückzugeben. Ich habe meinen Code geändert, um ein HttpException zu werfen, anstatt das HttpStatusCodeResult zurückzugeben, und jetzt funktioniert alles. Ich kann jeden HTTP-Statuscode zurückgeben, indem ich die Ausnahme HttpException auslöse und meine Konfiguration customErrors alle abfängt. Möglicherweise erledigt HttpStatusCodeResult nicht genau die Arbeit, die ich erwartet hatte.

Ich habe gerade ersetzt

context.Result = new System.Web.Mvc.HttpStatusCodeResult((int)System.Net.HttpStatusCode.Forbidden);

mit

throw new HttpException((int)System.Net.HttpStatusCode.Forbidden, "Forbidden");

Das ist es.

Fröhliches Codieren.

18
Haider

[1]: Entfernen Sie alle 'customErrors' und 'httpErrors' aus der Datei Web.config

[2]: Überprüfen Sie, ob "App_Start/FilterConfig.cs" folgendermaßen aussieht:

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

[3]: In 'Global.asax' füge diese Methode hinzu:

public void Application_Error(Object sender, EventArgs e)
{
    Exception exception = Server.GetLastError();
    Server.ClearError();

    var routeData = new RouteData();
    routeData.Values.Add("controller", "ErrorPage");
    routeData.Values.Add("action", "Error");
    routeData.Values.Add("exception", exception);

    if (exception.GetType() == typeof(HttpException))
    {
        routeData.Values.Add("statusCode", ((HttpException)exception).GetHttpCode());
    }
    else
    {
        routeData.Values.Add("statusCode", 500);
    }

    Response.TrySkipIisCustomErrors = true;
    IController controller = new ErrorPageController();
    controller.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
    Response.End();
}

[4]: Fügen Sie "Controllers/ErrorPageController.cs" hinzu

public class ErrorPageController : Controller
{
    public ActionResult Error(int statusCode, Exception exception)
    {
         Response.StatusCode = statusCode;
         ViewBag.StatusCode = statusCode + " Error";
         return View();
    }
}

[5]: in "Views/Shared/Error.cshtml"

@model System.Web.Mvc.HandleErrorInfo
@{
    ViewBag.Title = (!String.IsNullOrEmpty(ViewBag.StatusCode)) ? ViewBag.StatusCode : "500 Error";
}

<h1 class="error">@(!String.IsNullOrEmpty(ViewBag.StatusCode) ? ViewBag.StatusCode : "500 Error"):</h1>

//@Model.ActionName
//@Model.ControllerName
//@Model.Exception.Message
//@Model.Exception.StackTrace

: D

44
ubik404

Ich hatte auch dieses Problem. Der Code in der OP-Frage funktioniert einwandfrei, mit Ausnahme des benutzerdefinierten Fehlercodes im Abschnitt <system.web> In der Datei web.config. Um das Problem zu beheben, musste ich <system.webServer> Den folgenden Code hinzufügen. Beachten Sie, dass ‘webserver’ Anstelle von ‘web’ Steht.

<httpErrors errorMode="Custom" existingResponse="Replace">
  <remove statusCode="403" />
  <error statusCode="403" responseMode="ExecuteURL" path="/Error/UnAuthorized" />
</httpErrors>

Wenn jemand die folgende Umgebung verwendet, ist hier die vollständige Lösung:

Die Umwelt:

  • Visual Studio 2013 Update 4
  • Microsoft .NET Framework 4.5.1 mit ASP.NET MVC 5
  • Projekt: ASP.NET-Webanwendung mit MVC und Authentifizierung: Individuelle Benutzerkontovorlage

Benutzerdefinierte Attributklasse:

Fügen Sie die folgende Klasse zum Standardnamespace Ihrer Website hinzu. Der hier in der akzeptierten Antwort erläuterte Grund Frage zum Stapelüberlauf:Warum leitet AuthorizeAttribute bei Authentifizierungs- und Autorisierungsfehlern zur Anmeldeseite um?

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class AuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(System.Web.Mvc.AuthorizationContext filterContext)
    {
        if (filterContext.HttpContext.Request.IsAuthenticated)
        {
            filterContext.Result = new System.Web.Mvc.HttpStatusCodeResult((int)System.Net.HttpStatusCode.Forbidden);

        }
        else
        {
            base.HandleUnauthorizedRequest(filterContext);
        }
    }
} 

Fügen Sie dann den folgenden Code in die Datei web.config Ein

<system.webServer>
   <httpErrors errorMode="Custom" existingResponse="Replace">
      <remove statusCode="403" />
      <error statusCode="403" responseMode="ExecuteURL" path="/Error/UnAuthorized" />
   </httpErrors>
</system.webServer>

Der folgende Artikel erklärt mehr dazu: ASP.NET MVC: Verbessern des Berechtigungsattributs (403 Forbidden)

Und httpErrors in web.config Abschnitt in diesem Artikel: Demystifizieren von ASP.NET MVC 5-Fehlerseiten und Fehlerprotokollierung

Fügen Sie dann den ErrorController.cs zum Ordner Controllers hinzu

public class ErrorController : Controller
{
    // GET: UnAuthorized
    public ActionResult UnAuthorized()
    {
        return View();
    }

    public ActionResult Error()
    {
        return View();
    }

}

Fügen Sie dann einen UnAuthorized.cshtml zum Ordner View/Shared hinzu

@{
    ViewBag.Title = "Your Request Unauthorized !"; //Customise as required
 }
 <h2>@ViewBag.Title.</h2> 

Dadurch wird eine benutzerdefinierte Fehlerseite anstelle einer vom Browser generierten Fehlerseite angezeigt.

Beachten Sie auch, dass es in der obigen Umgebung nicht erforderlich ist, den Code in der RegisterGlobalFilters -Methode zu kommentieren, die von der Vorlage hinzugefügt wurde, wie in einer der Antworten vorgeschlagen.

Bitte beachten Sie, dass ich nur Code aus meinem Arbeitsprojekt ausgeschnitten und eingefügt habe. Daher habe ich im obigen Code Unauthorized anstelle von OPs NoPermissions verwendet.

13
Dush

da ich auf ein sehr ähnliches Problem stieß, wollte ich mehr Licht ins Dunkel bringen.

customErrors erfasst nur die tatsächlichen http-Ausnahmen, die in Ihrer ASP.NET-Anwendung ausgelöst wurden. Das HttpStatusCodeResult löst jedoch keine Ausnahme aus. Es wird lediglich eine Antwort mit dem entsprechenden Statuscode geschrieben, was in Ihrem Beispiel sinnvoller ist.

Wenn Sie mit IIS 7.0 oder höher arbeiten, sollten Sie jetzt httpErrors verwenden, da hierdurch in allen Fällen benutzerdefinierte Fehlerseiten angezeigt werden. Dies ist ein IIS Pegeleinstellung.

Ich habe einen ganzen Blog-Beitrag darüber geschrieben, um die Unterschiede zu erklären: http://dusted.codes/demystifying-aspnet-mvc-5-error-pages-and-error-logging

2
dustinmoris

Update

Sie müssen diese spezielle Umleitung nur für 403-Fehler ausführen. Alle anderen 500 Fehler sollten durch Ihr defaultRedirect="/Error/Error" Einstellung in customErrors. Sie müssen jedoch die HandleErrorAttribute-Registrierung in der Datei App_Start/FilterConfig.cs entfernen oder auskommentieren, damit benutzerdefinierte Fehler tatsächlich funktionieren. Andernfalls leitet dieses Attribut alle Fehler in die Datei Error.cshtml im Verzeichnis Views/Shared um.

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        // remove this line below
        //filters.Add(new HandleErrorAttribute());
    }
}

Ursprüngliche Antwort

Soweit ich weiß, können Sie customErrors in der web.config nicht verwenden, um aus irgendeinem Grund 403-Fehler zu behandeln. Ich empfinde Ihren Schmerz als etwas, das so einfach sein sollte wie der Code, den Sie bereits haben, aber anscheinend werden 403 Fehler als ein Webserver-Problem behandelt.

Stattdessen können Sie den Benutzer einfach auf die gewünschte "NoPermissions" -Seite umleiten:

public class CustomAuthorizeAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext context)
    {
        if (context.HttpContext.Request.IsAuthenticated)
        {
            context.Result = new RedirectToRouteResult(new RouteValueDictionary(new
            {
                action = "NoPermissions",
                controller = "Error",
                area = ""
            }));
        }
        else
        {
            base.HandleUnauthorizedRequest(context);
        }
    }
}

Die Anforderung hat einen 200-Statuscode anstelle eines 403-Statuscodes, aber wenn Sie damit leben können, ist dies eine einfache Problemumgehung.

Hier ist eine ähnliche SO Frage für weitere Informationen: Rückgabe benutzerdefinierter Fehler .

Außerdem wird in diesem Artikel erläutert, wie Sie die IIS) - Route einschlagen: http://kitsula.com/Article/MVC-Custom-Error-Pages

0
ryanulit