Ich konnte dieses Problem umgehen, indem ich das folgende Setup in asp.net-Webformularen mit .NET 3.5 verwendete.
Das von mir implementierte Muster umgeht die benutzerdefinierte Umleitungslösung von .NET in der web.config, da ich meine eigene geschrieben habe, um alle Szenarien mit dem richtigen HTTP-Statuscode im Header zu behandeln.
Zunächst sieht der Abschnitt customErrors der web.config folgendermaßen aus:
<customErrors mode="RemoteOnly" defaultRedirect="~/error.htm" />
Dieses Setup stellt sicher, dass der CustomErrors-Modus aktiviert ist, eine Einstellung, die wir später benötigen, und bietet eine Option für alle anderen Fehler für die defaultRedirect von error.htm. Dies ist nützlich, wenn ich keinen Handler für den spezifischen Fehler habe oder wenn eine Datenbankverbindung unterbrochen ist.
Zweitens ist hier das globale Asax-Fehlerereignis:
protected void Application_Error(object sender, EventArgs e)
{
HandleError();
}
private void HandleError()
{
var exception = Server.GetLastError();
if (exception == null) return;
var baseException = exception.GetBaseException();
bool errorHandled = _applicationErrorHandler.HandleError(baseException);
if (!errorHandled) return;
var lastError = Server.GetLastError();
if (null != lastError && HttpContext.Current.IsCustomErrorEnabled)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(lastError.GetBaseException());
Server.ClearError();
}
}
Dieser Code gibt die Verantwortung für die Behandlung des Fehlers an eine andere Klasse weiter. Wenn der Fehler nicht behandelt und CustomErrors aktiviert ist, bedeutet dies, dass wir einen Fall haben, in dem wir in Produktion sind und ein Fehler irgendwie nicht behandelt wurde. Wir werden es hier löschen, um zu verhindern, dass der Benutzer es sieht, aber melden Sie es in Elmah an, damit wir wissen, was los ist.
Die applicationErrorHandler-Klasse sieht folgendermaßen aus:
public bool HandleError(Exception exception)
{
if (exception == null) return false;
var baseException = exception.GetBaseException();
Elmah.ErrorSignal.FromCurrentContext().Raise(baseException);
if (!HttpContext.Current.IsCustomErrorEnabled) return false;
try
{
var behavior = _responseBehaviorFactory.GetBehavior(exception);
if (behavior != null)
{
behavior.ExecuteRedirect();
return true;
}
}
catch (Exception ex)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
}
return false;
}
Diese Klasse verwendet im Wesentlichen das Befehlsmuster, um den geeigneten Fehlerbehandler für den ausgegebenen Fehlertyp zu finden. Es ist wichtig, Exception.GetBaseException () auf dieser Ebene zu verwenden, da fast jeder Fehler in eine Ausnahme höherer Ebene eingeschlossen wird. Wenn Sie beispielsweise von einer Aspx-Seite aus "Neue System.Exception () auslösen" ausführen, wird auf dieser Ebene eine HttpUnhandledException empfangen, keine System.Exception.
Der "Factory" -Code ist einfach und sieht folgendermaßen aus:
public ResponseBehaviorFactory()
{
_behaviors = new Dictionary<Type, Func<IResponseBehavior>>
{
{typeof(StoreException), () => new Found302StoreResponseBehavior()},
{typeof(HttpUnhandledException), () => new HttpExceptionResponseBehavior()},
{typeof(HttpException), () => new HttpExceptionResponseBehavior()},
{typeof(Exception), () => new Found302DefaultResponseBehavior()}
};
}
public IResponseBehavior GetBehavior(Exception exception)
{
if (exception == null) throw new ArgumentNullException("exception");
Func<IResponseBehavior> behavior;
bool tryGetValue = _behaviors.TryGetValue(exception.GetType(), out behavior);
if (!tryGetValue)
_behaviors.TryGetValue(typeof(Exception), out behavior);
if (behavior == null)
Elmah.ErrorSignal.FromCurrentContext().Raise(
new Exception(
"Danger! No Behavior defined for this Exception, therefore the user might have received a yellow screen of death!",
exception));
return behavior();
}
Am Ende habe ich ein erweiterbares Fehlerbehandlungsschema eingerichtet. In jedem der definierten "Verhaltensweisen" habe ich eine benutzerdefinierte Implementierung für den Fehlertyp. Beispielsweise wird eine HTTP-Ausnahme auf den Statuscode überprüft und entsprechend behandelt. Für einen 404-Statuscode ist ein Server.Transfer anstelle eines Request.Redirect erforderlich, zusammen mit dem entsprechenden Statuscode, der in den Header geschrieben ist.
Hoffe das hilft.