در مطلب «ارتقاء به ASP.NET Core 1.0 - قسمت 3 - Middleware چیست؟» با اصول مقدماتی Middlewareها آشنا شدیم. همچنین در مطلب «آشنایی با OWIN و بررسی نقش آن در ASP.NET Core» یک مثال سفارشی از آنها، بررسی شد. در اینجا میخواهیم نکات بیشتری را در مورد تهیهی Middlewareهای سفارشی بررسی کنیم.
تفاوت بین متدهای app.Use و app.Run در چیست؟
Middlewareها به همان ترتیبی که در متد Configure کلاس آغازین برنامه معرفی میشوند، اجرا خواهند شد؛ اما نکتهی مهم اینجا است که middleware ایی که توسط متد app.Use تعریف میشود، میتواند middleware بعدی ثبت شدهرا، فراخوانی کند؛ اما app.Run خیر. برای درک بهتر این مفهوم، به مثال زیر دقت کنید:
اگر در این حالت برنامه را اجرا کنیم، چنین خروجی را مشاهده خواهیم کرد:
همانطور که در تصویر نیز مشخص است، ابتدا کدهای پیش از فراخوانی دلیگیت next میانافزار اول اجرا شدهاست. سپس باتوجه به فراخوانی دلیگیت next، کدهای دومین میانافزار ثبت شده، فراخوانی گردیدهاست و سپس کدهای پس از فراخوانی دلیگیت next میانافزار اول، اجرا شدهاند.
این دلیگیت در اصل یک چنین امضایی را دارد:
در اینجا چون میانافزار دوم از نوع app.Run است و قابلیت فراخوانی دلیگیت next را ندارد، از نوع terminal یا خاتمه دهنده بهشمار آمده و دیگر میان افزار بعدی ثبت شده، یعنی میانافزار سوم، اجرا نخواهد شد و کار پردازش برنامه در همین مرحله به پایان میرسد.
باید دقت داشت که فراخوانی دلیگیت next در میانافزارهای از نوع app.Use الزامی نبوده و اگر اینکار انجام نشود، بین app.Run و app.Use تفاوتی نخواهد بود و هر دو terminal به حساب میآیند.
تفاوت بین متدهایapp.Map و app.MapWhen در چیست؟
متد app.Map در صورت برآورده شدن شرطی، سبب اجرای میانافزاری مشخص میشود (امکان اجرای غیر خطی میانافزارها).
فرض کنید قطعه کد زیر را پس از اولین app.Use مثال فوق قرار دادهایم:
در این حالت اگر برنامه را اجرا کنیم، خروجی جدیدی را مشاهده نخواهیم کرد و خروجی حاصل دقیقا مانند تصویر مثال فوق است. اما اگر آدرس ویژهی dnt/ درخواست شود (الگوی تطابق اولین پارامتر متد Map)، آنگاه میان افزار ثبت شدهی app.Run ویژهی این حالت خاص، اجرا میشود:
در اینجا چون app.Run داخلی فراخوانی شده، از نوع terminal است، دیگر میان افزارهای پس از آن اجرا نشدهاند. بدیهی است در اینجا نیز میتوان به هر تعدادی که نیاز است میان افزارهای جدیدی را به appBuilder متد app.Map اضافه کرد.
پارامتر اول متد Map برای تطابق با الگوهایی خاص و مشخص، مناسب است. اما در اگر در اینجا نیاز به اطلاعات بیشتری از HttpContext جاری داشته باشیم، میتوانیم از متد app.MapWhen استفاده کنیم که اولین پارامتر آن یک دلیگیت است که HttpContext را در اختیار استفاده کننده قرار میدهد و اگر در نهایت true را دریافت کند، سبب اجرای میان افزارهای قسمت appBuilder آن خواهد شد:
در این مثال، شرط ارائه شدهی در پارامتر اول، اندکی پیچیدهتر است از حالت app.Map. در اینجا مشخص شدهاست که اگر آدرس دریافتی از کاربر، دارای کوئری استرینگی به نام dnt بود، آنگاه میان افزار(های) ارائه شدهی در قسمت appBuilder، اجرا شود. برای نمونه درخواست آدرس ذیل، سبب فراخوانی appBuilder.Run ذکر شده میشود:
نظم بخشیدن به تعاریف میانافزارها
متدهای app.Run و app.Use و امثال آنها برای تعریف سریع میان افزارها مناسب هستند. اما اگر بخواهیم کدهای کلاس آغازین برنامه را اندکی خلوت کرده و به تعاریف میانافزارها نظم ببخشیم، میتوان کدهای آنها را به کلاسهایی با امضایی خاص منتقل کرد:
در اینجا نحوهی تعریف یک کلاس میانافزار سفارشی را مشاهده میکنید. دو پارامتر context و next ایی را که در متد app.Use مشاهده کردید، دراینجا به نحو واضحتری مشخص شدهاند. دلیگیت next اشاره کنندهی به اجرای میان افزار بعدی، در سازندهی کلاس این میان افزار تزریق شدهاست. همچنین در اینجا میتوان سرویسهایی را که به IoC Container توکار ASP.NET Core معرفی کردهایم نیز تزریق کنیم و از این لحاظ محدودیتی ندارد (و همچنین امضای آن میتواند کاملا متغیر باشد). قسمت اصلی اجرایی این میان افزار، متد Invoke آن است که اطلاعات HttpContext جاری را در اختیار مصرف کننده قرار میدهد.
در اینجا نیز اگر دلیگیت next_ فراخوانی نشود، این میانافزار سبب خاتمهی اجرای پردازش درخواست جاری میگردد.
مرحلهی بعد، روش معرفی این میانافزار تعریف شده، به لیست میانافزارهای موجود است. برای این منظور میتوان متد app.UseMiddleware را به صورت مستقیم در کلاس آغازین برنامه فراخوانی کرد و یا مرسوم است اگر کتابخانهای را طراحی کردهاید، به نحو ذیل متد الحاقی خاصی را برای آن تدارک دید:
سپس مصرف کننده تنها باید این متد را در کلاس آغازین برنامه فراخوانی کند:
تفاوت بین متدهای app.Use و app.Run در چیست؟
Middlewareها به همان ترتیبی که در متد Configure کلاس آغازین برنامه معرفی میشوند، اجرا خواهند شد؛ اما نکتهی مهم اینجا است که middleware ایی که توسط متد app.Use تعریف میشود، میتواند middleware بعدی ثبت شدهرا، فراخوانی کند؛ اما app.Run خیر. برای درک بهتر این مفهوم، به مثال زیر دقت کنید:
using Microsoft.AspNetCore.Http; public class Startup { public void Configure(IApplicationBuilder app) { app.Use(async (context, next) => { await context.Response.WriteAsync("<div>from middleware-1, inside app.Use, before next()</div>"); await next(); await context.Response.WriteAsync("<div>from middleware-1, inside app.Use, after next()</div>"); }); app.Run(async context => { await context.Response.WriteAsync("<div>Inside middleware-2 defined using app.Run</div>"); }); app.Use(async (context, next) => { await context.Response.WriteAsync("<div>from middleware-3, inside app.Use, before next()</div>"); await next(); await context.Response.WriteAsync("<div>from middleware-3, inside app.Use, after next()</div>"); });
همانطور که در تصویر نیز مشخص است، ابتدا کدهای پیش از فراخوانی دلیگیت next میانافزار اول اجرا شدهاست. سپس باتوجه به فراخوانی دلیگیت next، کدهای دومین میانافزار ثبت شده، فراخوانی گردیدهاست و سپس کدهای پس از فراخوانی دلیگیت next میانافزار اول، اجرا شدهاند.
این دلیگیت در اصل یک چنین امضایی را دارد:
public delegate Task RequestDelegate(HttpContext context);
باید دقت داشت که فراخوانی دلیگیت next در میانافزارهای از نوع app.Use الزامی نبوده و اگر اینکار انجام نشود، بین app.Run و app.Use تفاوتی نخواهد بود و هر دو terminal به حساب میآیند.
تفاوت بین متدهایapp.Map و app.MapWhen در چیست؟
متد app.Map در صورت برآورده شدن شرطی، سبب اجرای میانافزاری مشخص میشود (امکان اجرای غیر خطی میانافزارها).
فرض کنید قطعه کد زیر را پس از اولین app.Use مثال فوق قرار دادهایم:
app.Map("/dnt", appBuilder => { appBuilder.Run(async context => { await context.Response.WriteAsync(@"<div>Inside Map(/dnt) --> Run</div>"); }); });
در اینجا چون app.Run داخلی فراخوانی شده، از نوع terminal است، دیگر میان افزارهای پس از آن اجرا نشدهاند. بدیهی است در اینجا نیز میتوان به هر تعدادی که نیاز است میان افزارهای جدیدی را به appBuilder متد app.Map اضافه کرد.
پارامتر اول متد Map برای تطابق با الگوهایی خاص و مشخص، مناسب است. اما در اگر در اینجا نیاز به اطلاعات بیشتری از HttpContext جاری داشته باشیم، میتوانیم از متد app.MapWhen استفاده کنیم که اولین پارامتر آن یک دلیگیت است که HttpContext را در اختیار استفاده کننده قرار میدهد و اگر در نهایت true را دریافت کند، سبب اجرای میان افزارهای قسمت appBuilder آن خواهد شد:
app.MapWhen(context => { return context.Request.Query.ContainsKey("dnt"); }, appBuilder => { appBuilder.Run(async context => { await context.Response.WriteAsync(@"<div>Inside MapWhen(?dnt) --> Run</div>"); }); });
http://localhost:7742/?dnt=true
نظم بخشیدن به تعاریف میانافزارها
متدهای app.Run و app.Use و امثال آنها برای تعریف سریع میان افزارها مناسب هستند. اما اگر بخواهیم کدهای کلاس آغازین برنامه را اندکی خلوت کرده و به تعاریف میانافزارها نظم ببخشیم، میتوان کدهای آنها را به کلاسهایی با امضایی خاص منتقل کرد:
using System.Threading.Tasks; using Microsoft.AspNetCore.Http; namespace Core1RtmEmptyTest.StartupCustomizations { public class MyMiddleware1 { private readonly RequestDelegate _next; public MyMiddleware1(RequestDelegate next) { _next = next; } public async Task Invoke(HttpContext context) { context.Response.ContentType = "text/html"; context.Response.StatusCode = 200; await context.Response.WriteAsync("<div>Hello from MyMiddleware1.</div>"); await _next.Invoke(context); await context.Response.WriteAsync("<div>End of action.</div>"); } } }
در اینجا نیز اگر دلیگیت next_ فراخوانی نشود، این میانافزار سبب خاتمهی اجرای پردازش درخواست جاری میگردد.
مرحلهی بعد، روش معرفی این میانافزار تعریف شده، به لیست میانافزارهای موجود است. برای این منظور میتوان متد app.UseMiddleware را به صورت مستقیم در کلاس آغازین برنامه فراخوانی کرد و یا مرسوم است اگر کتابخانهای را طراحی کردهاید، به نحو ذیل متد الحاقی خاصی را برای آن تدارک دید:
using Microsoft.AspNetCore.Builder; public static class MyMiddlewareExtensions { public static IApplicationBuilder UseMyMiddleware(this IApplicationBuilder app) { app.UseMiddleware<MyMiddleware1>(); return app; } }
public void Configure(IApplicationBuilder app) { app.UseMyMiddleware();
معمولا درون پوشه bin\debug یا bin\release تشکیل میشود.
اما جهت اطمینان میتونید مسیر دهی کامل کنید:
اما جهت اطمینان میتونید مسیر دهی کامل کنید:
string fileNameExisting = @"c:\Test.pdf"; string fileNameNew = @"c:\newform.pdf";
نظرات اشتراکها
به روز رسانی فایل OPML وبلاگهای IT ایرانی
نظرات مطالب
معرفی ES 6
آشنایی مقدماتی با جاوا اسکریپت.
نظرات مطالب
ASP.NET MVC #1
خیلی عالی بود و خوشحالم که با این سایت آشنایی پیدا کردم
با PushState آشنایی نداشتم ، خیلی جالب هست ، ممنونم.
نظرات نظرسنجیها
چه نوع محیط کاری را بیشتر ترجیح میدهید؟
آشنایی با محیط کار GitHub
نظرات مطالب
پیاده سازی Option یا Maybe در #C
سلام. ممنون از مطلب مفید شما.
شاید علت اینکه option در #C وجود نداره اینه که متد ()<Enumerable.Empty<TResult وجود داره و نیازی به این گزینه نیست. ولی در کل، هم فکر کردن در مورد NRE و هم آشنایی بیشتر با زبان #F مفید است. البته با توجه به اینکه این مقاله قبلا نوشته شده، باید بگم الان کامپایلر #C بسیار قویتر شده و تا حد زیادی جاهایی که احتمال وقوع این exception هست رو به شما خبر میده.
شاید علت اینکه option در #C وجود نداره اینه که متد ()<Enumerable.Empty<TResult وجود داره و نیازی به این گزینه نیست. ولی در کل، هم فکر کردن در مورد NRE و هم آشنایی بیشتر با زبان #F مفید است. البته با توجه به اینکه این مقاله قبلا نوشته شده، باید بگم الان کامپایلر #C بسیار قویتر شده و تا حد زیادی جاهایی که احتمال وقوع این exception هست رو به شما خبر میده.
The collection includes 14 different tools including a Json to Yaml and Yaml to Json converter, a JWT decoder, a Text compare tool, and more.
The full list includes:
- Converters
- Json <> Yaml
- Number Base
- Encoders / Decoders
- HTML
- URL
- Base64
- JWT Decoder
- Formatters
- Json
- Generators
- Hash (MD5, SHA1, SHA256, SHA512)
- UUID 1 and 4
- Lorem Ipsum
- Text
- Inspector & Case Converter
- Regex Tester
- Text Comparer
- Markdown Preview
- Graphic
- Color Blindness Simulator
- PNG / JPEG Compressor
Some of the tools will have wider appeal, for example, the text comparison tool would be useful for writers and solicitors alike, while the PNG/JPEG compressor could help webmasters. Expect more utilities to join the bundle in the future.
The collection is free, and can be accessed via GitHub here or free via the Microsoft Store.