مطالب
چگونه نرم افزارهای تحت وب سریعتری داشته باشیم؟ قسمت دوم
قسمت اول 

4. فشرده سازی HTTP را فعال کنید
اطمینان حاصل کنید که HTTP Compression در تمامی بخش‌های اصلی برنامه شما فعال است. حداقل کاری که می‌توانید در این رابطه بکنید این است که خروجی HTML که توسط برنامه شما تولید می‌شود را فشرده سازی کنید. جهت فعال سازی فشرده سازی در برنامه خود بهتر است در اولویت اول از ماژول ویژه ای که جهت این کار در IIS در نظر گرفته شده استفاده کنید. این ماژول تمامی کارها را به صورت خودکار برای شما انجام می‌دهد. اگر دسترسی به IIS جهت فعال سازی آن را ندارید، می‌توانید از ماژول‌های ASP.NET که جهت این کار تهیه شده استفاده کنید. می‌توانید کمی جستجو کنید و یا خودتان یکی تهیه کنید!

5.تنظیم CacheControlMaxAge
مقدار CacheControlMaxAge را در فایل web.config را طوری تنظیم کنید تا هیچ کاربری هیچ فایل static را دیگر درخواست نکند. مثلا می‌توانید این مقدار را بر روی چند ماه تنظیم کنید و البته فراموش نکنید این مقدار را در صفحات پویای خود بازنویسی (override) کنید تا مشکلی در رابطه با کش شدن فرم‌های اصلی برنامه (همانطور که در نکته اول بخش اول ذکر شد) پدید نیاید. البته کش کردن فایل‌های استاتیک برنامه بار مالی نیز برای شما و کاربرانتان خواهد داشت. دیگر هزینه پهنای باند اضافی جهت دانلود این فایل‌ها در هر درخواست برای شما (در سمت سرور) و کاربرانتان (در سمت کاربر) پرداخت نخواهد شد!

6. استفاده از OutputCache 
اگر از MVC استفاده می‌کنید، فراموش نکنید که از OutputCache در کنترل‌های MVC استفاده نمایید. اگر سرور شما بتواند اطلاعات را از رم خود بازیابی کند بهتر از آن است که آن را مجدد از دیتابیس واکشی نماید و عملیاتی نیز بر روی آن انجام دهد. البته مدیریت حافظه .NET به صورت خودکار کمبود حافظه را مدیریت کرده و از نشت حافظه جلوگیری خواهد کرد. برای توضیحات بیشتر در این رابطه می‌توانید از این مقاله کمک بگیرید.

7. بهره برداری از ORM Profiler
ORM Profiler ها تمامی فعالیت‌های ORM تحت نظر گرفته، دستورات T-SQL ارسالی به بانک اطلاعاتی را واکشی کرده و برای شما نمایش می‌دهند. تعدادی از آنها نیز این دستورات را آنالیز کرده پیشنهاداتی در رابطه با بهبود کارایی به شما ارائه می‌دهند. برای مثال به جای اینکه شما 2000 رکورد را یکی یکی از بانک بازیابی کنید، می‌توانید آن را به صورت یک query به بانک ارسال کنید. این موضوع به سادگی توسط ORM Profiler‌ها قابل بررسی است. نمونه ای از این نرم افزارها را می‌توانید در این سایت یا این سایت   پیدا کنید. البته در صورتی که نمی‌خواهید از نرم افزارهای جانبی استفاده کنید، می‌توانید از ابزارهای توکار بانک‌های اطلاعاتی مانند SQL Profiler نیز استفاده کنید (راهنمایی).
مطالب
فشرده سازی خروجی یک وب سرویس

جهت بهینه سازی روش ارائه شده در مقاله "بارگذاری یک یوزرکنترل با استفاده از جی‌کوئری" ، می‌توان مبحث فشرده سازی را نیز به آن افزود.
برای این منظور نیاز است تا بتوان response حاصل را کاملا کنترل کرد و این مورد از طریق یک http module به خوبی قابل انجام است. مبحث http compression و پیاده سازی آن‌را احتمالا بارها در سایت‌های مختلف نیز دیده‌اید:

using System;
using System.IO;
using System.IO.Compression;
using System.Globalization;
using System.Web;


public class JsonCompressionModule : IHttpModule
{
public JsonCompressionModule()
{
}

public void Dispose()
{
}

public void Init(HttpApplication app)
{
app.PreRequestHandlerExecute += new EventHandler(Compress);
}

private void Compress(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
HttpRequest request = app.Request;
HttpResponse response = app.Response;

if (request.ContentType.ToLower(CultureInfo.InvariantCulture).StartsWith("application/json"))
{
if (!((request.Browser.IsBrowser("IE")) && (request.Browser.MajorVersion <= 6)))
{
string acceptEncoding = request.Headers["Accept-Encoding"];

if (!string.IsNullOrEmpty(acceptEncoding))
{
acceptEncoding = acceptEncoding.ToLower(CultureInfo.InvariantCulture);

if (acceptEncoding.Contains("gzip"))
{
response.Filter = new GZipStream(response.Filter, CompressionMode.Compress);
response.AddHeader("Content-encoding", "gzip");
}
else if (acceptEncoding.Contains("deflate"))
{
response.Filter = new DeflateStream(response.Filter, CompressionMode.Compress);
response.AddHeader("Content-encoding", "deflate");
}
}
}
}
}
}
در این ماژول تنها درخواست‌هایی از نوع application/json بررسی خواهند شد. هر چند این فشرده سازی را بر روی خروجی هر نوع WebMethod ایی نیز می‌توان اعمال کرد. در این حالت، سطر بررسی json را حذف کرده و آن‌را به صورت زیر تغییر دهید:

if ( !request.Url.PathAndQuery.ToLower().Contains( ".asmx" ) )
return;
مرورگر IE6 و پایین‌تر نیز از این فشرده سازی معاف شده‌اند (چون یا پشتیبانی کاملی را ارائه نمی‌دهند یا باید منتظر کرش مرورگر بود).

جهت اعمال این ماژول به برنامه ASP.Net خود، کافی است سطر زیر را به قسمت httpModules وب کانفیگ افزود:

<httpModules>
<add name="JsonCompressionModule" type="JsonCompressionModule"/>
</httpModules>
روش آزمایش ماژول تهیه شده:

متاسفانه افزونه‌ی فایرباگ فایرفاکس اندازه‌ی نهایی response را نمایش می‌دهد و در گزارش آن حتی خبری از Content-encoding اضافه شده نیز نخواهد بود. بنابراین برای بررسی این روش مناسب نیست.
ابزار دیگری که اساسا برای این نوع آزمایشات طراحی شد‌ه است، برنامه معروف فیدلر می‌باشد (که توسط مدیر پروژه تیم IE برنامه نویسی شده است).
برای استفاده از فیدلر جهت دیباگ درخواست‌های local باید یک نکته‌ی کوچک را رعایت کرد:
http://localhost.:25413/

همانطور که در URL فوق مشاهده می‌کنید یک نقطه پس از localhost اضافه شده است تا خروجی محلی مربوطه قابل بررسی شود.



مطابق تصویر فوق، هم content-encoding اضافه شده مشخص است و هم حجم پاسخ دریافتی از 40 کیلوبایت (بر اساس یک تست معمولی روی صفحه‌ای مشخص) به نزدیک یک کیلوبایت و اندی کاهش یافته است.


اشتراک‌ها
9 کتابخانه جاوااسکریپتی جهت ایجاد نمودار
 So you have in your hand tons of data, with a number of variables, that you have to somehow relay to somebody else. Raw, unorganized data is going to be difficult for them to understand. This is why you need help from charts. In web design, charts are one of the best tools for data visualization. It is easy to read, easy on the eyes and relatively easy to set up. 
9 کتابخانه جاوااسکریپتی جهت ایجاد نمودار
مطالب دوره‌ها
ارتباطات بلادرنگ و SignalR
زمانیکه صحبت از برنامه‌های بلادرنگ می‌شود با کاربرانی سر و کار داریم که نیاز دارند تا اطلاعات مورد نیاز خود را همواره و بلافاصله در آخرین وضعیت به روز آن مشاهده کنند. در این بین، کلاینت می‌خواهد یک برنامه وب باشد یا سیلورلایت و یا یک برنامه نوشته شده با WPF. حتی برنامه‌های موبایل را نیز باید به این لیست اضافه کرد.
در اینجا کلمه بلادرنگ به معنای ارسال اطلاعات از طرف سرور به کلاینت‌ها با فاصله زمانی بسیار کوتاهی از به روز رسانی اطلاعات صورت گرفته در سمت سرور است.
نمونه‌ای از این برنامه‌ها شامل موارد ذیل هستند:
- اطلاع رسانی همزمان به گروهی از کاربران
- جستجوهای زنده و به روز رسانی‌هایی از این دست
- نمایش بلادرنگ قیمت‌ها و وضعیت تجاری محصولات و سهام‌ها
- بازی‌های تعاملی
- برنامه‌های گروهی و تعاملی (مانند برنامه‌های Chat)
- برنامه‌های شبکه‌های اجتماعی (برای مثال پیام جدیدی دارید؛ شخص خاصی آنلاین یا آفلاین شد و امثال آن)

بنابراین به صورت خلاصه قصد داریم به ارائه بازخوردها و اطلاع رسانی‌های بلادرنگ یا نسبتا سریع و به روز از سمت سرور به کلاینت‌ها برسیم.
برای مثال یک دیتاگرید را درنظر بگیرید. دو کاربر در شبکه صفحه یکسانی را گشوده‌اند و یکی از آن‌ها مشغول به ویرایش و یا حذف اطلاعات است. در ارتباطات بلادرنگ کاربر یا کاربران دیگر نیز باید (یا بهتر است) در زمانیکه گرید یکسانی را گشوده‌اند، بلافاصله آخرین تغییرات را ملاحظه کنند. یا حتی حالتی را درنظر بگیرید که شخصی SQL Server management studio را گشوده و در آنجا مشغول به تغییر اطلاعات گردیده است. در این حالت نیز بهتر است آخرین تغییرات بلافاصله به اطلاع کاربران رسانده شوند.

معرفی الگوی Push service

البته باید دقت داشت که الگوی push service یک الگوی رسمی ذکر شده در گروه‌های مرسوم الگوهای طراحی نیست، اما مفهوم آن سرویسی است که چندین کار ذیل را انجام می‌دهد:
الف) پذیرش اتصالات از چندین مصرف کننده. مصرف کننده‌ها در اینجا الزاما محدود به کلاینت‌های وب یا دسکتاپ نیستند؛ می‌توانند حتی یک سرور یا سرویس دیگر نیز باشند.
ب) قادر است اطلاعات را به مصرف کننده‌های خود ارسال کند. این سرویس می‌تواند یک برنامه ASP.NET باشد یا حتی یک سرویس متداول ویندوز.
ج) در اینجا چندین منبع خارجی مانند یک بانک اطلاعاتی یا تغییرات رخ داده توسط یک سخت افزار که می‌توانند سبب بروز رخدادهایی در push service گردند نیز می‌تواند وجود داشته باشند. هر زمان که تغییری در این منابع خارجی رخ دهد، مایل هستیم تا مصرف کننده‌ها را مطلع سازیم.


پروتکل HTTP و ارتباطات بلادرنگ

پروتکلی که در ارتباطات بلادرنگ مبتنی بر SignalR مورد استفاده قرار می‌گیرد، HTTP است و از قابلیت‌های Request و Response آن در اینجا بیشترین بهره برده می‌شود. پیاده سازی Push عموما بر مبنای یکی از روش‌های متداول زیر است:
1) Periodic polling
به این معنا که مثلا هر 10 ثانیه یکبار، کاری را انجام بده؛ مانند ارسال متناوب: آیا تغییری رخ داده؟ آیا تغییری رخ داده؟ و .... به همین ترتیب. این روش اصلا بهینه نبوده و منابع زیادی را خصوصا در سمت سرور مصرف خواهد کرد. برای مثال:
function getInfo() {
         $.ajax("url", function ( newInfo){
                  if ( newInfo != null) {
                      // do something with the data
                  }
         });
    // poll again after 20 seconds
    setTimeout(getInfo,20000);
}
// start the polling loop
getInfo();

2) Long polling
به آن HTTP Streaming یا Comet هم گفته می‌شود. این روش نسبتا هوشمند بوده و کلاینت اتصالی را به سرور برقرار خواهد کرد. سرور در این حالت تا زمانیکه اطلاعاتی را در دسترس نداشته باشد، پاسخی نخواهد داد. برای نمونه:
function getNewInfo(){
  $.ajax("url", function (newinfo) {
      // do something with the data
  // start the new request
      getNewINfo();
  });
}
// start the polling loop
getNewInfo();

این روش نسبت به حالت Periodic polling بهینه‌تر است اما نیاز به اتصالات زیادی داشته و همچنین تردهای بسیاری را در سمت سرور به خود مشغول خواهد کرد.

3) Forever frame
فقط در IE پشتیبانی می‌شود. در این روش یک Iframe مخفی توسط مرورگر تشکیل شده و از طریق آن درخواستی به سرور ارسال می‌شود. سپس سرور متناوبا با تزریق اسکریپت‌هایی به این Iframe سبب فراخوانی مجدد وضعیت خود می‌گردد. در این روش نیز به ازای هر درخواست و پاسخ، ارتباطات گشوده و بسته خواهند شد.

4) Server Sent Events یا SSE
این مورد جزو استاندارد HTML5 است. در اینجا اتصالی برقرار شده و داده‌ها از طریق اتصالات HTTP منتقل می‌شوند.
var eventSrc = new EventSource("url");
    // register event handler for the message
    eventSrc.addEventListener( "message",function (evt) {
    //process the data
});
این روش نیز بسیار شبیه به حالت long polling است. سرور تا زمانیکه اطلاعاتی را برای پاسخ دهی فراهم نداشته باشد، اتصال را باز نگه می‌دارد. به این ترتیب از لحاظ مقیاس پذیری گزینه بهتری است (نسبت به حالتیکه مدام اتصال برقرار و قطع می‌شود). اکثر مرورگرها منهای نگارش‌های قدیمی IE از این روش پشتیبانی می‌کنند.
تنها تفاوت آن با حالت long polling در این است که پس از ارائه پاسخ به کلاینت، اتصال را قطع نمی‌کند. Long polling نیز اتصال را باز نگه می‌دارد، اما این اتصال را بلافاصله پس از ارائه پاسخ، می‌بندد.

5) Web sockets
Web sockets در سکوی کاری ویندوز، تنها در ویندوز‌های 8، ویندوز سرور 2012 و دات نت 4 و نیم پشتیبانی می‌شود. هرچند این روش در حال حاضر به عنوان بهترین روش Push مطرح است اما به دلیل محدودیتی که یاد شد، مدتی طول خواهد کشید تا استفاده گسترده‌ای پیدا کند.
var socket = new WebSocket("url");
socket.onmessage = function (msg) {
var newInfo = msg.data;
// do something with the data
}
// client can also send request to server
socket.send(.... )
با این اوصاف آیا راه حل بهتر و میانه‌تری وجود دارد؟
بلی. اگر به وضعیت فعلی سکوی کاری ASP.NET نگاه کنیم:

SignalR را می‌توان مشاهده کرد که در گروه ساخت سرویس‌های آن قرار گرفته است. همانطور که ملاحظه می‌کنید، این سرویس جدید آنچنان وابستگی به سایر اجزای آن نداشته و می‌تواند خارج از ASP.NET نیز مورد استفاده قرار گیرد.

SignalR چیست؟

SignalR راه حلی است سمت سرور برای نوشتن push services. همچنین به همراه کتابخانه‌های سمت کاربری است که ارتباطات push services را در انواع و اقسام سکوهای کاری میسر می‌سازد. SignalR سورس باز بوده و برای اعمال غیرهمزمان (asynchronous) بهینه سازی شده است.
SignalR بر اساس مدل ذهنی اتصالات ماندگار (persistent connections) طراحی شده است. اتصالات ماندگار را باید به عنوان اتصالاتی سریع و غیرطولانی درنظر گرفت. در اینجا Signal یک اتصال است که اطلاعاتی به آن ارسال می‌گردد و هدف، انتقال قطعات کوچکی از اطلاعات است و هدف، ارسال حجم عظیمی از اطلاعات نیست. برای مثال اطلاع رسانی سریعی صورت گیرد که تغییراتی رخ داده است و سپس ادامه کار و دریافت اطلاعات واقعی توسط فرآیندهای متداول مثلا HTTP GET انجام شود. البته باید دقت داشت SignalR نیز نهایتا از یکی از 5 روش push بررسی شده در این قسمت استفاده می‌کند. اما بر اساس توانایی‌های کلاینت و سرور، به صورت هوشمند بهترین و بهینه‌ترین انتخاب را به کاربر ارائه می‌دهد.
اتصالات ماندگار قسمت سطح پایین SignalR را تشکیل می‌دهند. سطح بالاتر آن که این مفاهیم را به شکلی کپسوله شده ارائه می‌دهد، Hubs نام دارد که پایه اصلی دوره جاری را تشکیل خواهد داد.



همانطور که عنوان شد، SignalR سورس باز بوده و دارای مخزن کدی عمومی در GitHub است. همچنین بسته‌های تشکیل دهنده‌ی آن از طریق NuGet نیز قابل دریافت هستند. این بسته‌ها شامل هسته SignalR و کلاینت‌های آن مانند کلاینت‌های WinRT، سیلورلایت، jQuery، ویندوز فون8 و امثال آن هستند.

شروع کار با SignalR

تیم SignalR مثالی مقدماتی از نحوه کار با SignalR را به صورت یک بسته NuGet ارائه داده‌اند که از طریق آدرس و فرمان ذیل قابل دریافت است:
 PM> Install-Package Microsoft.AspNet.SignalR.Sample
قبل از اینکه این مثال را دریافت کنید نیاز است ابتدا یک برنامه ASP.NET جدید را آغاز نمائید (تفاوتی نمی‌کند که MVC باشد یا Web forms). سپس دستور فوق را فراخوانی کنید.

پس از دریافت مثال، یکبار پروژه را کامپایل کرده و سپس بر روی فایل StockTicker.html آن کلیک راست نموده و گزینه مشاهده در مرورگر را انتخاب کنید. همچنین برای اینکه این مثال را بهتر مشاهده کنید، بهتر است دو وهله از مرورگر را باز کرده و آدرس باز شده را در آن بررسی کنید تا اعمال تغییرات همزمان به کلاینت‌های متفاوت را بهتر بتوان بررسی و مشاهده کرد.

اشتراک‌ها
کتابخانه ای جهت پیاده سازی Unobtrusive Ajax در ASP.NET Core

AspNetCore.Unobtrusive.Ajax 

Unobtrusive Ajax Helpers (like MVC5 Ajax.BeignForm and Ajax.ActionLink) for ASP.NET Core 

Features

  • Works with Upload file.
  • Works with [AntiForgeryTokenValidation].
  • Has [AjaxOnly] attribute to limit actions.
  • Has httpRequest.IsAjaxRequest() extension method to check request is ajax and decide return PartialView or JSON result.
  • Additional overloads for ease of use.
  • Adds necessary JS script automatically when you use a Ajax Helpers and remove JS script when you no longer use it (Optional - is by default).
  • Uses CDN url instead of Embedded script (Optional - isn't by default). 
کتابخانه ای جهت پیاده سازی Unobtrusive Ajax در ASP.NET Core
مطالب
نگاهی به تغییرات فایل Program.cs در نگارش‌های مختلف ASP.NET Core تا نگارش 6
در طی سال‌های قبل، نحوه‌ی آغاز برنامه‌های ASP.NET Core دچار تغییرات زیادی شده‌است که حداقل سه مورد مهم آن‌ها به صورت زیر است:
- استفاده از WebHost.CreateDefaultBuilder: این روش جهت تنظیم شروع به کار یک برنامه‌ی ASP.NET Core 2x مورد استفاده قرار می‌گرفت.
- استفاده از Host.CreateDefaultBuilder: روش پیش‌فرض آغاز برنامه‌های وب NET Core 3x. و NET 5x. که با معرفی generic host، امکان تهیه‌ی Worker services را میسر کردند.
- استفاده از WebApplication.CreateBuilder: روش جدید شروع به کار با برنامه‌های وب مبتنی بر NET 6.


استفاده از WebHost.CreateDefaultBuilder در ASP.NET Core 2.x

در نگارش اول ASP.NET Core، مفهومی به نام هاست پیش‌فرض (default host) وجود نداشت. یکی از مهم‌ترین نکات درنظر گرفته شده در طراحی ASP.NET Core، مفهوم «هزینه کردن به ازای احتیاج» است. یعنی اگر نیاز به قابلیتی نیست، نباید وجود داشته باشد. به این ترتیب یک قالب آغازین نباید به همراه تعداد زیادی بسته‌‌های NuGet و مقدار زیادی کد برای تنظیم باشد؛ زمانیکه واقعا قرار نیست از تمام آن‌ها استفاده شود. به همین جهت از نگارش 2، شروع به ساده‌کردن این قالب اولیه کردند و در این زمان، WebHost.CreateDefaultBuilder ارائه شد. این تنظیم به ظاهر ساده، کدهای پیش‌فرض مورد نیاز قابل توجهی را جهت ساخت ساده‌ی IWebHostBuilder و IWebHost به همراه دارد. در قالب به همراه آن، بین مفاهیم تنظیمات application و host تفاوت قائل شده‌اند؛ یعنی دو فایل Program.cs را برای تنظیمات application و فایل Startup.cs را برای ارائه‌ی تنظیمات هاست، تدارک دیدند.
در این طراحی، بین میدان دید Program و Startup تفاوت وجود دارد. هدف از Program، ارائه‌ی تنظیمات زیرساختی برنامه، مانند تنظیمات HTTP Server، یکپارچگی با IIS و امثال آن شد و عموما در طول عمر برنامه ثابت است. اما برای تغییر رفتار برنامه، بیشتر تغییرات و تنظیمات، به Startup محول شدند؛ مانند تنظیمات تزریق وابستگی‌ها، تنظیمات میان‌افزارها، مسیریابی‌ها و غیره.
public class Program
{
    public static void Main(string[] args)
    {
        BuildWebHost(args).Run();
    }

     public static IWebHost BuildWebHost(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>()
            .Build();
}
نمونه‌ا‌ی از فایل Program.cs برنامه‌های ASP.NET Core 2x را در اینجا ملاحظه می‌کنید این تنظیم ساده، کار خواندن فایل appsettings.json و برپایی تنظیمات برنامه، تنظیمات logging و همچنین تنظیمات یکپارچگی با Kestrel/IIS را در پشت صحنه انجام می‌دهد. همچنین ارجاعی را نیز به کلاس Startup برنامه دارد. متد UseStartup به صورت خودکار به دنبال متدهای ویژه‌ی ConfigureServices و Configure در کلاس آغازین برنامه گشته و آن‌ها را فراخوانی می‌کند تا تنظیمات تزریق وابستگی‌ها، مسیریابی‌ها و میان‌افزارها صورت گیرند.


معرفی Generic Host در ASP.NET Core 3.x/5

ASP.NET Core 3.x به همراه تغییرات بزرگی در کدهای آغازین برنامه‌های ASP.NET Core بود. تا پیش از آن، امکانات پایه‌ی ASP.NET Core تنها برای مقاصد وب قابل استفاده بود. اما در نگارش‌های 3x، با ارائه‌ی یک هاست عمومی، امکان پشتیبانی از سایر برنامه‌ها، مانند worker services را نیز میسر کرد؛ برای مثال پیشتیبانی از کارهای طولانی پس زمینه، هاست سرویس‌های gRPC، هاست سرویس‌های ویندوز و غیره. هدف اصلی از این تغییرات، به اشتراک گذاری فریم‌ورک پایه‌ی ASP.NET Core که تنها برای برنامه‌های وب ساخته شده بود و به همراه امکاناتی مانند تنظیمات، ثبت وقایع، تزریق وابستگی‌ها و غیره بود، با سایر انواع برنامه‌های یاد شده است. برای رسیدن به این هدف، Web Host نگارش 2x، به Generic Host نگارش 3x تغییر کرد و سپس ASP.NET Core برفراز آن بنا شد. اینبار بجای IWebHostBuilder، نمونه‌ی جدید IHostBuilder را داریم:
public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            }; 
    }
}
در اینجا نمونه‌ا‌ی از فایل Program.cs برنامه‌های ASP.NET Core 3x را ملاحظه می‌کنید. با توجه به عمومی بودن این روش، قسمت ConfigureWebHostDefaults آن، همان کار WebHost.CreateDefaultBuilder نگارش 2 ASP.NET Core را انجام می‌دهد.
ASP.NET Core 5 به همراه تغییرات مهمی در این زمینه نبود و تنها با تغییر target framework در فایل csproj و به روز رسانی بسته‌های نیوگت مرتبط، کار ارتقاء به نگارش جدید در آن صورت می‌گرفت.


معرفی  WebApplicationBuilder در ASP.NET Core 6x  

در دات نت 6، روش آغاز برنامه‌های وب بطور کامل تغییر کرده‌است. در تمام نگارش‌های پیشین ASP.NET Core، همواره شاهد دو فایل Program.cs و Startup.cs بودیم؛ اما در اینجا فقط یک فایل Program.cs بیشتر وجود ندارد. هر چند همانطور که در مطلب «ارتقاء فایل‌های آغازین برنامه‌های ASP.NET Core 5x به 6x» نیز عنوان شد، می‌توان همان سبک و سیاق پیشین را نیز برگرداند و از این لحاظ محدودیتی وجود ندارد.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
   app.UseDeveloperExceptionPage();
}
app.UseStaticFiles();
app.MapGet("/", () => "Hello World!");
app.MapRazorPages();
app.Run();
در اینجا نمونه‌ای از فایل Program.cs برنامه‌های دات نت 6 را مشاهده می‌کنید که تغییرات قابل ملاحظه‌ای داشته‌است:
- استفاده از top level statements
- استفاده از usingهای سراسری و سایر قابلیت‌های C# 10.0
- حذف کامل کلاس Startup؛ اینبار همه چیز فقط یک فایل است.

دیدگاهی را که در اینجا بکار گرفته‌اند شامل این موارد است و بیشتر تازه‌واردان را مدنظر دارند:
- برای شروع به کار، using statements اضافی هستند؛ پس حذف شده‌اند!
- برای شروع به کار، namespaces اضافی هستند؛ پس حذف شده‌اند!
- برای شروع به کار، Program.Main ... هم اضافی است!
- تنظیمات بین دو فایل Program.cs و Startup.cs تقیسم نشده‌اند و همه‌چیز یکجا است و این هم نیازی به توضیح اضافی به تازه‌واردان، ندارد.
- همچنین همانطور که عنوان شد، « ... متد UseStartup به صورت خودکار به دنبال متدهای ویژه‌ی ConfigureServices و Configure در کلاس آغازین برنامه گشته و آن‌ها را فراخوانی می‌کند تا تنظیمات تزریق وابستگی‌ها، مسیریابی‌ها و میان‌افزارها صورت گیرند ...»
نکته‌ی مهم این توضیح، این است که کلاس Startup، هیچ اینترفیسی را پیاده سازی نمی‌کند. یعنی نام این متدها، دقیقا باید به همین صورت باشند (بدون اینکه قرار دادی توسط یک اینترفیس برای آن‌ها وضع شده باشد) و ... چرا واقعا باید به این صورت باشد؟! به همین جهت این‌ها هم حذف شده‌اند!
- در اینجا WebApplication هم مشاهده می‌شود؛ اما آیا واقعا نیازی به آن است؟
پاسخ: خیر! WebApplication.CreateBuilder ای که در اینجا ملاحظه می‌کنید در حقیقت ساده شده‌ی قطعه کد زیر از کدهای ASP.NET Core 3x/5x است:
var hostBuilder = Host.CreateDefaultBuilder(args)
    .ConfigureServices(services => 
    {
        services.AddRazorPages();
    })
    .ConfigureWebHostDefaults(webBuilder =>
    {
        webBuilder.Configure((ctx, app) => 
        {
            if (ctx.HostingEnvironment.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            app.UseStaticFiles();
            app.UseRouting();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapGet("/", () => "Hello World!");
                endpoints.MapRazorPages();
            });
        });
    }); 
hostBuilder.Build().Run();
که ... WebApplication.CreateBuilder بدون شک ساده‌تر از قطعه کد فوق است. همچنین پس از یک سطر زیر:
 var builder = WebApplication.CreateBuilder(args);
با استفاده از خاصیت builder.Configuration، می‌توان به تنظیمات برنامه دسترسی یافت و یا با استفاده از builder.Services می‌توان سرویس‌های جدیدی را ثبت کرد:
builder.Services.AddRazorPages();
builder.Services.AddSingleton<MyThingy>();
و یا با استفاده از خاصیت builder.Logging می‌توان تنظیمات ثبت وقایع برنامه را تغییر داد:
builder.Logging.AddFile();
همچنین در اینجا زمانیکه کار تنظیمات به پایان رسید، نمونه‌ای از WebApplication را به صورت زیر تولید کرده:
var app = builder.Build();
و اکنون می‌توان تنظیمات میان‌افزارها و یا مسیریابی‌ها را انجام داد:
app.UseStaticFiles();
app.MapRazorPages();
که در مقایسه با نگارش‌های قبلی، بسیار ساده‌تر شده‌، هرچند مرز بین این‌ها و ترتیب آن‌ها اندکی کم‌رنگ‌تر شده‌است.
مطالب
انتشار پیش نمایش ASP.NET Identity 2.0.0-alpha1
مایکروسافت در تاریخ 20 دسامبر 2013 پیش نمایش نسخه جدید ASP.NET Identity را معرفی کرد. تمرکز اصلی در این انتشار، رفع مشکلات نسخه 1.0 بود. امکانات جدیدی هم مانند Account Confirmation و Password Reset اضافه شده اند.

دانلود این انتشار
ASP.NET Identity را می‌توانید در قالب یک پکیج NuGet دریافت کنید. در پنجره Manage NuGet Packages می‌توانید پکیج‌های Preview را لیست کرده و گزینه مورد نظر را
نصب کنید. برای نصب پکیج‌های pre-release توسط Package Manager Console از فرامین زیر استفاده کنید.
  • Install-Package Microsoft.AspNet.Identity.EntityFramework -Version 2.0.0-alpha1 -Pre
  • Install-Package Microsoft.AspNet.Identity.Core -Version 2.0.0-alpha1 -Pre
  • Install-Package Microsoft.AspNet.Identity.OWIN -Version 2.0.0-alpha1 -Pre
دقت کنید که حتما از گزینه "Include Prerelease" استفاده می‌کنید. برای اطلاعات بیشتر درباره نصب پکیج‌های Pre-release لطفا به این لینک و یا این لینک مراجعه کنید.

در ادامه لیست امکانات جدید و مشکلات رفع شده را می‌خوانید.

Account Confirmation
سیستم ASP.NET Identity حالا از Account Confirmation پشتیبانی می‌کند. این یک سناریوی بسیار رایج است. در اکثر وب سایت‌های امروزی پس از ثبت نام، حتما باید ایمیل خود را تایید کنید. پیش از تایید ثبت نام قادر به انجام هیچ کاری در وب سایت نخواهید بود، یعنی نمی‌توانید Login کنید. این روش مفید است، چرا که از ایجاد حساب‌های کاربری نامعتبر (bogus) جلوگیری می‌کند. همچنین این روش برای برقراری ارتباط با کاربران هم بسیار کارآمد است. از آدرس‌های ایمیل کاربران می‌توانید در وب سایت‌های فروم، شبکه‌های اجتماعی، تجارت آنلاین و بانکداری برای اطلاع رسانی و دیگر موارد استفاده کنید.

نکته: برای ارسال ایمیل باید تنظیمات SMTP را پیکربندی کنید. مثلا می‌توانید از سرویس‌های ایمیل محبوبی مانند  SendGrid  استفاده کنید، که با Windows Azure براحتی یکپارچه می‌شود و از طرف توسعه دهنده اپلیکیشن هم نیاز به پیکربندی ندارد.

در مثال زیر نیاز دارید تا یک سرویس ایمیل برای ارسال ایمیل‌ها پیکربندی کنید. همچنین کاربران پیش از تایید ایمیل شان قادر به بازنشانی کلمه عبور نیستند.

Password Reset
این هم یک سناریوی رایج و استاندارد است. کاربران در صورتی که کلمه عبورشان را فراموش کنند، می‌توانند از این قابلیت برای بازنشانی آن استفاده کنند. کلمه عبور جدیدی بصورت خودکار تولید شده و برای آنها ارسال می‌شود. کاربران با استفاده از این رمز عبور جدید می‌توانند وارد سایت شوند و سپس آن را تغییر دهند.

Security Token Provider
هنگامی که کاربران کلمه عبورشان را تغییر می‌دهند، یا اطلاعات امنیتی خود را بروز رسانی می‌کنند (مثلا حذف کردن لاگین‌های خارجی مثل فیسبوک، گوگل و غیره) باید شناسه امنیتی (security token) کاربر را بازتولید کنیم و مقدار قبلی را Invalidate یا بی اعتبار سازیم. این کار بمنظور حصول اطمینان از بی اعتبار بودن تمام شناسه‌های قبلی است که توسط کلمه عبور پیشین تولید شده بودند. این قابلیت، یک لایه امنیتی بیشتر برای اپلیکیشن شما فراهم می‌کند. چرا که وقتی کاربری کلمه عبورش را تغییر بدهد از همه جا logged-out می‌شود. یعنی از تمام مرورگرهایی که برای استفاده از اپلیکیشن استفاده کرده خارج خواهد شد.

برای پیکربندی تنظیمات این قابلیت می‌توانید از فایل Startup.Auth.cs استفاده کنید. می‌توانید مشخص کنید که میان افزار OWIN cookie هر چند وقت یکبار باید شناسه امنیتی کاربران را بررسی کند. به لیست زیر دقت کنید.
// Enable the application to use a cookie to store information for the signed in user
// and to use a cookie to temporarily store information about a user logging in with a third party login provider
// Configure the sign in cookie
app.UseCookieAuthentication(newCookieAuthenticationOptions {
    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
    LoginPath = newPathString("/Account/Login"),
    Provider = newCookieAuthenticationProvider {
        OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
            validateInterval: TimeSpan.FromSeconds(5),
            regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
    }
});

امکان سفارشی کردن کلید‌های اصلی Users و Roles

در نسخه 1.0 نوع فیلدهای کلید اصلی در جداول Users و Roles از نوع رشته (string) بود. این بدین معنا است که وقتی از Entity Framework و Sql Server برای ذخیره داده‌های ASP.NET Identity استفاده می‌کنیم داده‌های این فیلد‌ها بعنوان nvarchar ذخیره می‌شوند. درباره این پیاده سازی پیش فرض در فروم هایی مانند سایت StackOverflow بسیار بحث شده است. و در آخر با در نظر گرفتن تمام بازخورد ها، تصمیم گرفته شد یک نقطه توسعه پذیری (extensibility) اضافه شود که توسط آن بتوان نوع فیلدهای اصلی را مشخص کرد. مثلا شاید بخواهید کلیدهای اصلی جداول Users و Roles از نوع int باشند. این نقطه توسعه پذیری مخصوصا هنگام مهاجرت داده‌های قبلی بسیار مفید است، مثلا ممکن است دیتابیس قبلی فیلدهای UserId را با فرمت GUID ذخیره کرده باشد.

اگر نوع فیلدهای کلید اصلی را تغییر دهید، باید کلاس‌های مورد نیاز برای Claims و Logins را هم اضافه کنید تا کلید اصلی معتبری دریافت کنند. قطعه کد زیر نمونه ای از نحوه استفاده این قابلیت برای تعریف کلیدهای int را نشان می‌دهد.
de Snippet
publicclassApplicationUser : IdentityUser<int, CustomUserLogin, CustomUserRole, CustomUserClaim>
{
}
publicclassCustomRole : IdentityRole<int, CustomUserRole>
{
    public CustomRole() { }
    public CustomRole(string name) { Name = name; }
}
publicclassCustomUserRole : IdentityUserRole<int> { }
publicclassCustomUserClaim : IdentityUserClaim<int> { }
publicclassCustomUserLogin : IdentityUserLogin<int> { }
 
publicclassApplicationDbContext : IdentityDbContext<ApplicationUser, CustomRole, int, CustomUserLogin, CustomUserRole, CustomUserClaim>
{
}

پشتیبانی از IQueryable روی Users و Roles

کلاس‌های UserStore و RoleStore حالا از IQueryable پشتیبانی می‌کنند، بنابراین می‌توانید براحتی لیست کاربران و نقش‌ها را کوئری کنید.
بعنوان مثال قطعه کد زیر دریافت لیست کاربران را نشان می‌دهد. از همین روش برای دریافت لیست نقش‌ها از RoleManager می‌توانید استفاده کنید.
//
// GET: /Users/
public async Task<ActionResult> Index()
{
    return View(await UserManager.Users.ToListAsync());
}

پشتیبانی از عملیات Delete از طریق UserManager

در نسخه 1.0 اگر قصد حذف یک کاربر را داشتید، نمی‌توانستید این کار را از طریق UserManager انجام دهید. اما حالا می‌توانید مانند قطعه کد زیر عمل کنید.
var user = await UserManager.FindByIdAsync(id);

if (user == null)
{
    return HttpNotFound();
}

var result = await UserManager.DeleteAsync(user);

میان افزار UserManagerFactory

شما می‌توانید با استفاده از یک پیاده سازی Factory،  وهله ای از UserManager را از OWIN context دریافت کنید. این الگو مشابه چیزی است که برای گرفتن AuthenticationManager در OWIN context استفاده می‌کنیم.  این الگو همچنین روش توصیه شده برای گرفتن یک نمونه از UserManager به ازای هر درخواست در اپلیکیشن است.
قطعه کد زیر نحوه پیکربندی این میان افزار در فایل StartupAuth.cs را نشان می‌دهد.
// Configure the UserManager
app.UseUserManagerFactory(newUserManagerOptions<ApplicationUserManager>()
{
    DataProtectionProvider = app.GetDataProtectionProvider(),
    Provider = newUserManagerProvider<ApplicationUserManager>()
    {
        OnCreate = ApplicationUserManager.Create
    }
});
و برای گرفتن یک وهله از UserManager:
HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();

میان افزار DbContextFactory

سیستم ASP.NET Identity از Entity Framework برای ذخیره داده هایش در Sql Server استفاده می‌کند. بدین منظور، ASP.NET Identity کلاس ApplicationDbContext را رفرنس می‌کند. میان افزار DbContextFactory به ازای هر درخواست در اپلیکیشن یک وهله از ApplicationDbContext را به شما تحویل می‌دهد.
می توانید پیکربندی لازم را در StartupAuth.cs انجام دهید.
app.UseDbContextFactory(ApplicationDbContext.Create);

Samples

امکانات جدید را می‌توانید در پروژه https://aspnet.codeplex.com پیدا کنید. لطفا به پوشه Identity در سورس کد مراجعه کنید. برای اطلاعاتی درباره نحوه اجرای پروژه هم فایل readme را بخوانید.

برای مستندات ASP.NET Identity 1.0 هم به  http://www.asp.net/identity  سر بزنید. هنوز مستنداتی برای نسخه 2.0 منتشر نشده، اما بزودی با انتشار نسخه نهایی مستندات و مثال‌های جدیدی به سایت اضافه خواهند شد.

Known Issues
در کنار قابلیت‌های جدیدی مانند Account Confirmation و Password Reset، دو خاصیت جدید به کلاس IdentityUser اضافه شده اند: 'Email' و 'IsConfirmed'. این تغییرات الگوی دیتابیسی که توسط ASP.NET Identity 1.0 ساخته شده است را تغییر می‌دهد. بروز رسانی پکیج‌ها از نسخه 1.0 به 2.0 باعث می‌شود که اپلیکیشن شما دیگر قادر به دسترسی به دیتابیس عضویت نباشد، چرا که مدل دیتابیس تغییر کرده. برای بروز رسانی الگوی دیتابیس می‌توانید از Code First Migrations استفاده کنید.

نکته: نسخه جدید به EntityFramework 6.1.0-alpha1 وابستگی دارد، که در همین تاریخ (20 دسامبر 2013) پیش نمایش شد.  http://blogs.msdn.com/b/adonet/archive/2013/12/20/ef-6-1-alpha-1-available.aspx

EntityFramework 6.1.0-alpha1 بروز رسانی هایی دارد که سناریوی مهاجرت در ASP.NET Identity را تسهیل می‌کند، به همین دلیل از نسخه جدید EF استفاده شده. تیم ASP.NET هنوز باگ‌های زیادی را باید رفع کند و قابلیت‌های جدیدی را هم باید پیاده سازی کند. بنابراین پیش از نسخه نهایی RTM شاهد پیش نمایش‌های دیگری هم خواهیم بود که در ماه‌های آتی منتشر می‌شوند.

برای اطلاعات بیشتر درباره آینده ASP.NET Identity به لینک زیر سری بزنید.