Request pipeline w ASP.NET 5 działa na zasadzie middleware, co to znaczy?
Dla mnie najprościej było to zrozumieć poprzez analogię do głuchego telefonu, zabawy w którą chyba każdy z nas się bawił :)
Gluchy telefon
Nie jestem pewny jakie są prawa autorskie tego obrazka, znalezione w sieci bez żadnego info
Chodzi o to, że jak wchodzi request to przekazywany jest on do pierwszej osoby, jeżeli jej nie ma, to request po prostu się kończy i tyle, nic się nie dzieje. Jeżeli osoba jest to teraz wszystko zależy od tej osoby: czy ona go zmodyfikuje? Przekaże dalej? Może nie chce się już bawić? Na tej samej zasadzie działa middleware.
Wchodzi request i przekazywany jest on do PIERWSZEGO zadeklarowanego middleware, ten zaś może z nim zrobić wszystko co chce i albo przekazać dalej, albo ustawić kontynuację jak wiadomość do niego wróci. Jeżeli middleware się zdecyduje by przekazać wiadomość dalej, trafi ona do DRUGIEGO zadeklarowanego middleware – nie do trzeciego czy czwartego, ale do DRUGIEGO. Jest to łańcuszek.
Czyli jeżeli nasz PIERWSZY middleware wywali błąd, zaś DRUGI ma go przechwycić to raczej nic z tego ;) gdyż do DRUGIEGO request nawet nie dojdzie, zostanie przerwany przy PIERWSZYM. To tak jak w głuchym telefonie, jak pierwsza osoba powie NIE BAWIE SIĘ, to druga nie usłyszy co ma przekazać dalej…
A więc bardzo ważna rzecz – KOLEJNOŚĆ w middleware ma znaczenie.
Ok a jak wygląda takie middleware? W najprostszej postaci tak:
app.Run(async ctx => { ctx.Response.StatusCode = 200; ctx.Response.ContentType = "text/html"; await ctx.Response.WriteAsync("<h1>Hello, World!</h1>"); });
Jest to middleware które kończy request, nie zawiera ono delegata do wykonania kolejnego middleware, czyli jeżeli tutaj nic nie obsłużymy to już nic nie obsłużymy.
Inną opcją jest użycie middleware w takiej postaci:
app.Use(async (ctx, next) => ctx.Response.ContentType = "text/html"; await ctx.Response.WriteAsync("<h1>HACKED</h1>"); await next(); });
Tym razem mamy delegat next
który jak zostanie wykonany przekaże request do NASTĘPNEGO middleware. Jeżeli nie, to request się kończy i dalej nie pójdzie.
Istnieje jeszcze opcja stworzenia klasy implementującej middleware i następnie wykorzystanie jej za pomocą metody UseMiddleware
:
public class HackMiddleware { RequestDelegate _next; public HackMiddleware(RequestDelegate next) { _next = next; } public async Task Invoke(HttpContext ctx) { await ctx.Response.WriteAsync("<h1>HACKED AGAIN!</h1>"); await _next(ctx); } } // in Startup: app.UseMiddleware<HackMiddleware>();
Większość dodatków do ASP.NET 5 korzysta do tego z extension methods by umożliwić prostsze rejestrowanie middleware (tak jak na przykład UseMvc
):
public static class MyHackMiddlewareExtensions { public static IApplicationBuilder UseHack(this IApplicationBuilder app) { return app.UseMiddleware<HackMiddleware>(); } } // in Startup.cs: app.UseHack();
Czy teraz jest to trochę bardziej zrozumiałe? Macie pomysły jak możecie to wykorzystać? :) Ja na przykład napisałem middleware który jak tylko gdzieś zobaczy napis „gutek” to zwraca mi stronę: „U Ciebie i tak nic nie zadziała Gutek” :)
Skończy się walką z przyjaznymi linkami w aplikacji, które chcemy tworzyć dynamicznie przy współpracy z bazą danych. Dróg do realizacji tego jest sporo, ale teraz widzę że wystarczy stworzyć Middlewere który połączy się z bazą i sprawdzi czy dla przekazanego URI nie można by dodać jakiś dodatkowych “ekstra” parametrów Request, które później złapie RouteMap :)
Popraw mój błąd ortograficzny :)
oj tam oj tam :) żadnego ort nie było ;)
Jakub Gutkowski o dev i nie tylko | ASP.NET 5 – middleware – krótko ale trafnie – Jakub Gutkowski o dev i nie tylko
Dziękujemy za dodanie artykułu – Trackback z dotnetomaniak.pl
Comments are closed.