حالا چطور و چگونه ازش استفاده کنیم؟!
این Extension کارش این است، وقتی HttpClient ما مقدار دهی شده و آمادهی برای ارسال درخواست به سرویس بیرونی است، میتوانیم قبل ارسال، آن را فراخوانی کنیم و یک خروجی Curl از درخواستی را که داریم میفرستیم، ببینیم. سپس خروجی Curl را در ترمینال صدا بزنیم و نتیجه را ببینیم. همینطور میتوانیم به Postman خود Import کنیم و با داکیومنتی که داده شده، بررسی کنیم و مشکل را دقیقتر بررسی کنیم.
نحوه Import کردن Curl در Postman
open the Postman -> click on the Import button -> select the Raw text tab -> paste the curl script here -> then press the Continue button -> at the end press the button import.
استفاده از این Extension بسیار ساده و سریع است و شما با نوشتن یک خط میتوانید آن را فراخوانی کنید:
این Extension سه(۳) راه برای نمایش Curl دارد:
۱- چاپ در Console
httpClient.GenerateCurlInConsole(httpRequestMessage, null);
httpClient.GenerateCurlInConsole( httpRequestMessage, configs => { configs.TurnOn = true; configs.NeedAddDefaultHeaders = true; configs.EnableCodeBeautification = false; });
- با مقدارNeedAddDefaultHeaders میتوانید مشخص کنید در صورت داشتن هدرهای پیش فرض، در خروجی Curl اضافه شود یا خیر. پیش فرض آن فعال هست.
- مقدارEnableCodeBeautification اگر فعال باشد اسکریپتهای چاپ شده در Console را به ازای هر HttpMethod، با رنگ متفاوتی نشان میدهد؛ برای خوانایی بهتر اسکریپت. بصورت پیش فرض غیر فعال است.
۲- ذخیره در فایل
httpClient.GenerateCurlInFile(httpRequestMessage, null);
مثال و توضیحات کانفیگ به شرح زیر است:
httpClient.GenerateCurlInFile( httpRequestMessage, configs => { configs.Filename = "your filename"; configs.Path = "your path"; configs.TurnOn = true; configs.NeedAddDefaultHeaders = true; });
- مقدارPath را میتوانید در صورت داشتن مسیری خاص، مشخص کنید. در غیر این صورت بصورت پیش فرض اطلاعات را در مسیر ProjectDirectory\bin\Debug\netX ذخیره میکند.
- مقدارTurnOn پیش فرض آن فعال است. درصورت غیرفعال کردن جنریتور غیر فعال میشود و عمل ایجاد اسکریپت را انجام نمیدهد.
- با مقدار NeedAddDefaultHeaders میتوانید مشخص کنید در صورت داشتن هدرهای پیش فرض، در خروجی Curl اضافه شود یا خیر. پیش فرض آن فعال هست.
۳- ذخیره در متغیر
httpClient.GenerateCurlInString(httpRequestMessage);
لینک آدرس GitHub پروژه جهت دیدن سورس پروژه و دیدن مثالهای بیشتر و همینطور برای دیدن قابلیتهای بیشتر این extension.
خوشحال میشوم اگه نظری دارید راجع به پروژه و یا مشکلی دیدید در سورس کد به من اطلاع بدهید و خیلی خوشحال میشوم اگر در تکمیل و پیاده سازی این پروژه مشارکت کنید و اگر این پروژه براتون جذاب و یا مفید بود استار بدهید.
آزمایش بار برنامههای داتنت با k6
سری مقدماتی داتنت بر روی Azure
.NET on Azure for Beginners
8 videos
.NET on Azure for Beginners will teach you the basics of Azure and how to leverage its services and features to build amazing cloud applications. You will learn how to deploy web apps, work with storage and data, authenticate and use Managed Identity, harness the power of containers, and even deploy with GitHub Actions. By the end of this series, you will have the skills and confidence to start developing your own .NET applications on Azure!
داتنت ۷ ریلیز شد!
.NET 7 brings your apps increased performance and new features for C# 11/F# 7, .NET MAUI, ASP.NET Core/Blazor, Web APIs, WinForms, WPF and more. With .NET 7, you can also easily containerize your .NET 7 projects, set up CI/CD workflows in GitHub actions, and achieve cloud-native observability.
Thanks to the open-source .NET community for your numerous contributions that helped shape this .NET 7 release. 28k contributions made by over 8900 contributors throughout the .NET 7 release!
.NET remains one of the fastest, most loved, and trusted platforms with an expansive .NET package ecosystem that includes over 330,000 packages.
آشنایی با AOP Interceptors
- اما توسط پارامتر IInvocation و مقداری Reflection، دسترسی کاملی به اطلاعات متد فراخوان هست و در اینجا میتوان در صورت نیاز، پارامتر و مقداری را نیز به آن ارسال کرد.
- در ASP.NET MVC، مفهوم فیلترها دقیقا پیاده سازی کنندهی Interceptorهای AOP هستند. در اینجا نیز مستقیما اطلاعاتی به فراخوان، در صورت نیاز بازگشت داده نمیشود. اما Context جاری در اختیار Interceptor و فیلتر هست. به این ترتیب Interceptor فرصت خواهد داشت به این Context مشترک، اطلاعاتی را اضافه کند یا تغییر دهد. مثلا به لیست خطاهای آن یک خطای اعتبارسنجی جدید را اضافه کند.
انتشار نسخه اول پیشنمایش داتنت ۸
Welcome to .NET 8! The first preview is ready for you to download: claim your copy of the first .NET 8 preview and start building applications today. Scroll down to see the list of features included in this preview. .NET 8 is a long-term support (LTS) release. This blog post covers the major themes and goals that drive the prioritization and selection of enhancements to develop. .NET 8 preview and release candidate builds will be delivered monthly. As usual, the final release will be delivered sometime in November at .NET Conf.
public class TestController { private readonly ILogger<TestController> _logger; public TestController(ILogger<TestController> logger) { _logger = logger; } [HttpGet("/")] public string Get() { _logger.LogInformation("hello world"); return "Hello world!"; } }
اگر یک چنین برنامهای را به دات نت 6 ارتقاء دهید، با پیام اخطار زیر مواجه خواهید شد:
CA1848: For improved performance, use the LoggerMessage delegates instead of calling LogInformation
استفادهی گسترده از source generators در دات نت 6
source generators، امکان مداخله در عملیات کامپایل برنامه را میسر کرده و امکان تولید کدهای پویایی را در زمان کامپایل، فراهم میکنند. هرچند این قابلیت به همراه دات نت 5 ارائه شدند، اما تا زمان دات نت 6 استفادهی گستردهای از آن در خود دات نت صورت نگرفت. موارد زیر، تغییراتی است که بر اساس source generators در دات نت 6 رخ دادهاند:
- source generators مخصوص ILogger (موضوع این بحث؛ یعنی LoggerMessage source generator)
- source generators مخصوص System.Text.Json تا سربار تبدیل به JSON و یا برعکس کمتر شود.
- بازنویسی مجدد پروسهی کامپایل Blazor/Razor بر اساس source generators، بجای روش دو مرحلهای قبلی که امکان Hot Reload را فراهم کردهاست.
نوشتن یک source generator هرچند ساده نیست، اما چون نیاز به reflection را به حداقل میرساند، میتواند تغییرات کارآیی بسیار مثبتی را به همراه داشته باشد.
توصیه به استفاده از LoggerMessage.Define در دات نت 6
ILogger به همراه قابلیتهایی مانند structural logging نیز هست که امکان فرمت بهتر پیامهای ثبت شده را میسر میکند تا توسط برنامههای جانبی که قرار است این لاگها را پردازش کنند، به سادگی قابل خواندن باشند. برای مثال رکورد زیر را در نظر بگیرید:
public record Person (int Id, string Name);
var person = new Person(123, "Test");
_logger.LogInformation("hello to {Person}", person);
info: TestController[0] hello world to Person { Id = 123, Name = Test }
اگر در اینجا مانند مثال زیر از string interpolation استفاده شود:
_logger.LogInformation($"hello world to {person}"); // Using interpolation instead of structured logging
- ویژگی «لاگهای ساختار یافته» را از دست میدهیم و دیگر توسط نرم افزارهای ثالث لاگ خوان، به سادگی پردازش نخواهند شد.
- ویژگی «قالب ثابت» پیام را نیز از دست خواهیم داد که باز هم یافتن پیامهای مشابه را در بین انبوهی از لاگهای رسیده مشکل میکند.
- کار serialization شیء ارسالی به آن، پیش از عملیات ثبت وقایع رخ میدهد. اما ممکن است سطح لاگ سیستم در این حد نباشد و اصلا این پیام لاگ نشود. در این حالت یک کار اضافی صورت گرفته و بر روی کارآیی برنامه تاثیر منفی خواهد گذاشت.
برای جلوگیری از serialization و همچنین تخصیص حافظهی اضافی و مشکلات عدم ساختار یافته بودن لاگها، توصیه شدهاست که ابتدا سطح لاگ مدنظر بررسی شود و همچنین از string interpolation استفاده نشود:
if (_logger.IsEnabled(LogLevel.Information)) { _logger.LogInformation("hello world to {Person}", person); }
مشکل دیگر لاگهای ساختار یافته، امکان فراموش کردن یکی از پارامترها است که با یک خطای زمان اجرا گوشزد خواهد شد؛ مانند مثال زیر:
_logger.LogInformation("hello world to {Person} because {Reason}", person);
private static readonly Action<ILogger, Person, Exception?> _logHelloWorld = LoggerMessage.Define<Person>( logLevel: LogLevel.Information, eventId: 0, formatString: "hello world to {Person}");
اکنون روش فراخوانی این Action با کارآیی بالا به صورت زیر است:
[HttpGet("/")] public string Get() { var person = new Person(123, "Test"); _logHelloWorld(_logger, person, null); return "Hello world!"; }
معرفی [LoggerMessage] source generator در دات نت 6
هرچند LoggerMessage.Define، مزایای قابل توجهی مانند کش شدن قالب لاگ، عدم نیاز به بررسی ضرورت لاگ شدن پیام و ارسال تعداد پارامترهای صحیح را به همراه دارد، اما ... کار کردن با آن مشکل است و برای کار با آن باید کدهای زیادی را نوشت. به همین جهت با استفاده از قابلیت source generators، امکان تولید خودکار این نوع کدها در زمان کامپایل برنامه پیشبینی شدهاست:
public partial class TestController { [LoggerMessage(0, LogLevel.Information, "hello world to {Person}")] partial void LogHelloWorld(Person person); }
ویژگی partial method، امکان تعریف یک متد را در یک فایل و سپس ارائهی پیاده سازی آنرا در فایلی دیگر میسر میکند که البته در اینجا آن فایل دیگر، توسط source generator تولید میشود.
باید دقت داشت که در اینجا TestController را نیز باید به صورت partial تعریف کرد تا آن نیز قابلیت بسط در چند فایل را پیدا کند. همچنین متد فوق را به صورت static partial void نیز میتوان نوشت.
یکی از مزایای کار با source generator که خودش در اصل یک آنالایزر هم هست، بررسی تعداد پارامترهای ارسالی و تعریف شدهاست:
[LoggerMessage(0, LogLevel.Information, "hello world to {Person} with a {Reason}")] partial void LogHelloWorld(Person person);
در این روش، امکان ذکر پارامتر اختیاری LogLevel هم وجود دارد؛ اگر نیاز است مقدار آن به صورت پویا تغییر کند:
[LoggerMessage(Message = "hello world to {Person}")] partial void LogHelloWorld(LogLevel logLevel, Person person);