7

Ich schreibe eine asp.net 4.5-Anwendung mit den neuen Routing-Funktionen. Ich habe eine Seite, auf der Informationen zu einem Artikel angezeigt werden. Im Page_Load Ereignis überprüfe ich die Routendaten (Artikel-ID) und Benutzerberechtigungen, und wenn etwas nicht stimmt (z. B. die ID für ein gelöschtes Objekt), verwende ich Response.RedirectToRoute, um sie packen, direkt zurück auf die Homepage. Überhole GO nicht, sammle keine $ 200 ein.Korrekte Möglichkeit, die Seitenausführung nach Response.RedirectToRoute zu überspringen

Das machte Sinn, bis ich versuchte, auf ein gelöschtes Objekt zuzugreifen, und anstelle der Homepage bekam ich eine Fehlerseite. Ich habe etwas graben und festgestellt, dass auch nach der Verwendung von RedirectToRoute (im Gegensatz zu der Standard Redirect Methode) der Rest der Seite Code continues to execute, die zumindest verschwenderisch scheint (da ich nur die Ergebnisse wegwerfen werde) und Fehler wirft wenn die notwendigen Daten nicht existieren.

Ich habe ein wenig mehr SO Bergbau und entdeckte die unglaubliche evil das ist Response.End(). Es tut, was ich brauche, aber selbst die MSDN page sagt mir, dass Response.End ist das Bastard Kind einer alten verfluchten Sprache und ist nicht geeignet, um das Licht des Tages zu sehen. Der primäre Einwand scheint die Tatsache zu sein, dass Response.End eine Ausnahme auslöst, und das ist schlecht für die Leistung. Ich bin nicht der erfahrenste Entwickler, daher verstehe ich das Problem nicht vollständig, aber ich habe Schwierigkeiten zu glauben, dass das Auslösen einer Ausnahme teurer ist als das Laden der gesamten Webseite. Die workarounds scheinen für eine so einfache Aufgabe ziemlich komplex und übertrieben zu sein, zumal die meisten Seiten eine Art Gültigkeitsprüfung erfordern.

Was soll ich in dieser Situation tun? Benutze Response.End und bitte um Verzeihung für meine Unverschämtheit? Cobble zusammen ein hässlicher Workaround? Oder ist meine Perspektive auf das Problem alles falsch? Ich würde es wirklich gerne wissen.

Update: Nun, da ich es ein wenig mehr überlegt habe, frage ich mich, ob ich die falsche Perspektive auf das Problem habe. Vielleicht ist eine sofortige Weiterleitung nicht die beste Antwort für die Benutzererfahrung. Wäre es besser, alle Steuerelemente in einem Panel zu verpacken und so etwas zu verwenden?

Private Sub Page_Init(sender As Object, e As EventArgs) Handles Me.Init 
    'Validation Code 
    If notValid Then 
     ControlsPanel.Visible = false 
     ErrorPanel.Visible = true 
    End If 
End Sub 

Antwort

3

Ich gehe aus einem Bein heraus, indem ich die Frage nicht direkt beantworte, aber ich mochte dein Update bezüglich der Benutzerfreundlichkeit. Ich bevorzuge Ihren vorgeschlagenen Ansatz.

Ich mag einen 410 Fehler für ids geben, die nicht gültig sind und verlängern sie ein wenig mit (von C# übersetzt):

Protected Sub ItemDoesNotExist() 
'item does not exist, serve up error page 
ControlsPanel.Visible = False 
ErrorPanel.Visible = True 

'add meta tags for noindex 
Dim mymeta As New HtmlMeta() 
mymeta.Name = "robots" 
mymeta.Content = "noindex" 
Page.Header.Controls.Add(mymeta) 

'RESPOND WITH A 410 
Response.StatusCode = 410 
Response.Status = "410 Gone" 
Response.StatusDescription = "Gone" 
Response.TrySkipIisCustomErrors = True 
'important for IIS7, otherwise the Custom error page for 404 shows. 
Page.Title = "item gone" 
End Sub 
+0

Danke für die Folge oben. Mir ist nicht aufgefallen, dass du mit einem Fehlercode antworten und die Seite trotzdem laden kannst. Das werde ich mir in Zukunft unbedingt merken. –

9

RedirectToRoute ist eigentlich wickelt Response.Redirectfalse zum Beenden der Anfrage vorbei - damit geht die Anfrage. Sie können HttpApplication.CompleteRequest als sofortigen Aufruf verwenden, um die Anforderung zu beenden, damit die nächsten Anwendungsereignisse nicht aufgerufen werden.

Response.End (und andere Variation Redirect) throws ThreadAbortException die Anfrage Verarbeitungsthread abzubrechen, die wirklich eine schlechte Weise Anforderungsverarbeitung zu beenden. In der .NET-Welt wird die Verarbeitung von Exceptions immer als teuer angesehen, da CLR dann den gesamten Stack nach Ausnahmeverarbeitungsblöcken suchen, Stack-Traces erstellen muss usw. IMO, CompleteRequest wurde in .NET 1.1 eingeführt, um das zu vermeiden, was tatsächlich erforderlich ist Setzen des Flags im ASP.NET-Infrastrukturcode, um die weitere Verarbeitung mit Ausnahme des Ereignisses EndRequest zu überspringen.

Noch ein (und besserer) Weg ist es, Server.Transfer zu verwenden und Client Round-Trip zu vermeiden, um Redirect alle zusammen zu setzen. Das einzige Problem ist, dass der Client die umgeleitete URL nicht in der Adressleiste des Browsers sehen kann. Ich bevorzuge diese Methode in der Regel.

EDIT
CompleteRequest würde nicht nie in Seiten Fall arbeiten, wo nachfolgende Seite Ereignisse aufgerufen noch werden würden, weil Seite ein Handler zu sein, alle seine Ereignisse geschehen in einem einzigen (und Strom) Anwendungsereignis ProcessRequest.So einzige Weg scheint eine Flagge zu sein Einstellung und prüfen Sie diese Fahne in Überschreibungen wie Render, PreRender, RaisePostBackEvent usw.

Aus Wartung Sicht ist es sinnvoll, eine solche Funktionalität in der Basisseitenklasse zu haben (dh die Aufrechterhaltung der Flagge, Angebot CompleteRequest Methode zu Unterklassen und zum Überschreiben von Lebenszyklus - Ereignismethoden). Zum Beispiel:

+1

Vielen Dank für Ihre Antwort. Ich bemerkte, dass 'CompleteRequest' als bessere Option vorgeschlagen wurde, aber es führt auch weiterhin den gesamten Code auf der Seite aus. Verschiedene Steuerelemente auf der Seite erhalten ihre Daten vom Element, und wenn sie nicht vorhanden sind, werfen sie Fehler, sodass ich eine Fehlerseite anstelle einer Umleitung erhalte. Ich könnte durchgehen und auf jeder Methode auf Gültigkeit prüfen, aber das scheint _rather_ unnötig und weniger wartbar. –

+0

Ich finde es interessant, dass Sie 'Server.Transfer' erwähnen. Obwohl ich den Vorteil der Vermeidung einer Hin- und Rückreise zu schätzen weiß, habe ich nicht das Gefühl, dass diese Methode für meine Zwecke gut funktionieren würde, da die aktuelle URL des Nutzers ungültig ist. Ich habe auch gelesen, dass 'Server.Transfer'' Response.End' aufruft und ich sehe keine Überlastung der Funktion, um dies zu vermeiden. –

+2

@probackpacker, bitte akzeptiere meine Entschuldigung! 'CompleteRequest' wirkt sich auf Pipeline-Ereignisse aus, aber das aktuelle Handler-Ereignis würde fortgesetzt. Es gibt keinen anderen Weg, als mit dem Flag innerhalb der Seite zu überprüfen - aus der Wartungsperspektive können Sie das in eine wiederverwendbare Basisseitenklasse extrahieren (siehe meine Bearbeitung). – VinayC

Verwandte Themen