Sep.19

ASP.NET Page refresh afvangen

Bij het bouwen van ASP.NET webapplicaties is het gebruik van de browser “back”-knop niet aan te raden. In het gunstigste geval treden er geen problemen op maar in andere gevallen zijn de problemen die op kunnen treden vervelend. Neem bijvoorbeeld het dubbel toevoegen van gegevens. Een gebruiker is niet zomaar ander gedrag aan te leren dus zal je als programmeur een oplossing moeten zoeken voor dit probleem. Er bestaan oplossingen voor dit probleem en 1 daarvan is de volgende.

Wat gebeurt er eigenlijk.

  1. Een gebruiker opent een pagina in de webbrowser, laten we zeggen inschrijven.aspx. Op deze pagina kunnen gegevens worden opgeslagen. (Roundtrip 1)
  2. De gebruiker voert zijn persoonsgegevens in en drukt op de opslaan knop. De pagina wordt gepost naar de server. Op de server pagina wordt het click event van de opslaan knop afgehandeld. De gegevens worden met behulp van een insert query in de database weggeschreven. Vervolgens wordt een specifieke view op de inschrijven pagina getoond waar bij de gebruiker wordt geinformeerd over het feit dat de gegevens succesvol zijn opgeslagen. Daarbij wordt een link getoond waarmee de gebruiker terug kan keren naar de homepage, home.aspx. (Roundtrip 2)
  3. De gebruiker klikt op de link en de homepage wordt getoond. (Roundtrip 3)

Roundtrips.jpg
Maar..
De gebruiker bedenkt zich, hij heeft de tekst niet goed gelezen en kiest de back button.

en dan beginnen de problemen…

De browser zal een post uitvoeren met de gegevens die zijn ingevoerd op bij inschrijving. Het click event opslaan wordt opnieuw uitgevoerd en de gegevens worden middels insert opnieuw in de database geschreven. 🙁 .. dat willen we natuurlijk niet. Het zou mooi zijn als op dat moment duidelijk is dat een refresh wordt uitgevoerd. Ofwel een request dat al een keer eerder is uitgevoerd door de gebruiker.

Als eerste dient er een base page te worden aangemaakt die een property IsRefreshed heeft. Met behulp van deze property kunnen we in alle overerfde pages gebruik maken van deze property. De logica die in de base page wordt geimplementeerd is vrij eenvoudig. Bij elke request van de gebruiker maken we een ticket aan. Dit ticket behelst een uniek gegenereerd nummer in dit geval heb ik gekozen voor een Guid, deze zou ten alle tijden uniek moeten zijn.
Roundtrips2.jpg

Wat is een GUID
Voor degenen die niet weten hoe een Guid er uit ziet, hier een voorbeeld:
{56CCB843-F919-4bdf-AC18-823710BEDB3F}
Middels de methode Guid.NewGuid() kan men het .NET framework een nieuwe Guid laten genereren.

Bij response wordt het ticket in de viewstate van de pagina die de gebruiker voorgeschoteld krijgt opgeslagen. Daarnaast wordt de het ticket ook opgeslagen in de gebruikerspecifieke sessie. Deze acties worden uitgevoerd in het PreRender event van de page. Bij postback (request) door de gebruiker (opslaan inschrijving) wordt via de viewstate van de page het ticket teruggegeven. Bij het oproepen van de IsRefreshed property vlag wordt gecontroleerd of het laatste uitgegeven ticket, vastgelegd in de sessie overeenkomt met het ticket in de viewstate van de page. Wordt er dus een oude request uitgevoerd dan zal ook een oud ticket worden teruggegeven en zal dus niet overeenkomen met het laatste ticket in de sessie waarmee dus bekend is dat de page een refresh heeft gehad. Als er een gewone reguliere postback plaatsvind zal het ticket van de page overeenkomen met het ticket in de sessie en dus herkend worden als een niet-refresh.
Roundtrips3.jpg
Of een pagina gerefreshed is wordt overigens alleen gecontroleerd bij een postback. Bij postbacks treden namelijk de eerder genoemde problemen op. De gebruiker moet wel in staat zijn diverse pagina’s meerdere keren te bezoeken waarbij het niet relevant is of deze is gerefreshed.

De code:

Wil je gebruik maken van deze oplossing dan is het enige wat er moet gebeuren dat je webpagina’s niet laten overerven van Page maar van bovenstaande RefreshSupportPage.

Deel dit Verhaal:
  • facebook
  • twitter
  • gplus

Over Ton Snoei

Een enthousiaste ontwikkelaar in de allerbreedste zin van het woord.

Het aansturen maar vooral coachen van mensen geeft me veel plezier en een leuke uitdaging. Ik houdt me graag bezig met het bouwen van software maar ook met alle anderen dingen die komen kijken bij het vak dat IT heet.

Met als achtergrond ontwikkelaar heb ik veel ervaring met C# .NET en alles wat daarbij komt kijken. Deze kennis komt nog regelmatig goed van pas. Mijn liefde voor ontwikkeling van software is nooit verdwenen en heb mij daarom in het afgelopen jaar meer verdiept in Java, Android, iOS/iPhone/iPad (Monotouch/Xamarin), PHP en Unity 3D development. Ik noem dat altijd maar: "Lego-spelen voor grote mensen" ;-)

Kortom van de grote lijnen naar projecten tot hands-on problem solven.

Laat een reactie achter

Comment