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.