اشتراک‌ها
مقدمه ای بر Visual Studio Dev

Visual Studio Dev Essentials is a new free developer offering from Microsoft. A free membership to this program gives you access to a range of benefits including developer tools and services, training and support. This video provides an overview of some key benefits, including Visual Studio Community, Visual Studio Team Services, Pluralsight training, and HackHands live programming help 

مقدمه ای بر Visual Studio Dev
اشتراک‌ها
انتشار VS 2015 Update 1 و TFS 2015 Update 1
اشتراک‌ها
انتشار Tools for Apache Cordova Update 3
Three weeks ago, we released Visual Studio Tools for Apache Cordova Update 2. Last week, we introduced you to a new TACO CLI. Now we’re back with Update 3, which is automatically included when you install Visual Studio 2015. If you’re an existing user of Visual Studio 2015, you’ll receive a notification to download and install today.
انتشار Tools for Apache Cordova Update 3
اشتراک‌ها
کتاب Visual Studio 2015 Succinctly

In Visual Studio 2015 Succinctly, author Alessandro Del Sole explains how to take advantage of the highly anticipated features in Microsoft Visual Studio 2015. Topics include sharing code between different types of projects, new options for debugging and diagnostics, and improving productivity with other services in the Visual Studio ecosystem, such as NuGet and Azure.

کتاب Visual Studio 2015 Succinctly
اشتراک‌ها
10 ویژگی عالی از Visual Studio Code
Enter Visual Studio Code – a free, lean, cross-platform version of your beloved Visual Studio. With a lightweight installation, you can enjoy most full-featured benefits of Visual Studio on a Windows, Mac or Linux machine. This article highlights 10 of the compelling features of VS Code, which aims to be your one-stop rich code editor across any developer platform.
10 ویژگی عالی از Visual Studio Code
مطالب
آشنایی با WPF قسمت سوم: Layouts بخش دوم

  در مقاله قبلی در مورد تعدادی از Layout‌ها صحبت کردیم و در این بخش به ادامه‌ی آن پرداخته و دو مبحث GridPanel و Custom Layout را بررسی می‌کنیم.


GridPanel

پنل پیش فرضی است که موقع ایجاد یک پروژه‌ جدید WPF ایجاد می‌شود. چیدمان این نوع پنل به صورت سطر و ستون است و کارکرد آن بسیار مشابه جداول در HTML می‌باشد؛ با این تفاوت که در اینجا انعطاف پذیری بیشتری وجود دارد. هر سلول می‌تواند شامل چندین کنترل شود و یا هر کنترل می‌تواند چندین سلول را به خود احتصاص دهند و حتی می‌تواند روی کنترل‌های دیگر قرار بگیرند و همپوشانی کنترل‌ها را داشته باشیم.

تگ Grid Panel شامل دو تگ برای تعریف سطرها و ستون‌ها می‌باشد با استفاده از تگ Row Definition و Column Definition به تعیین تعداد سطر و ستون‌ها و اندازه آن‌ها می‌پردازیم:
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
        <RowDefinition Height="28" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition Width="200" />
    </Grid.ColumnDefinitions>
</Grid>
گرید پنل بالا شامل 4 سطر و دو ستون است و تعیین اندازه آن‌ها توسط دو خاصیت Width و  Height مشخص شده است که نحوه مقداردهی آن‌ها به صورت زیر است:
Fixed : یک مقدار ثابت، مثل سطر آخری که در کد بالا قرار می‌گیرد. این مقدار بر اساس یک واحد منطقی است و نه پیکسل که در این مقاله قبلا بررسی کرده‌ایم.
Auto : به مقداری که احتیاج دارد فضایی را بخود اختصاص می‌دهد.
* : هر آنچه از فضای موجود باقی مانده است را به خود اختصاص می‌دهد. علامت ستاره یک واحد نسبی است؛ به این صورت که می‌توانید مقدار فضا را به صورت زیر نیز بیان کنید.*3 و *2 به این معنی است که از پنج قسمت فضای باقیمانده سه قسمت و بعدی دو قسمت  را به خود اختصاص می‌دهد. عبارت * با *1 برابر است. عموما با این علامت فضا را به شکل درصد بیان می‌کنند:
 <ColumnDefinition Width="69*" />   <!-- Take 69% of remainder -->
    <ColumnDefinition Width="31*"/> <!-- Take 31% of remainder -->

نحوه‌ی اضافه کردنالمان‌ها به گرید به صورت زیر پس از تعیین تعداد سطرها و ستون‌ها انجام می‌گیرد و جایگاه هر المان در ستون یا سطر مربوطه توسط یک attached Dependency Property به نام‌های Grid.Column یا Grid.Row صورت می‌گیرد. خصوصیات Horizontal alignment و vertical Alignment هم برای تعیین موقعیت قرار گیری اشیاء در سلول به کار می‌روند و فاصله‌ی آن‌ها (کنترل ها) از لبه‌های گرید با margin محاسبه می‌شود.
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
        <RowDefinition Height="28" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition Width="200" />
    </Grid.ColumnDefinitions>
    <Label Grid.Row="0" Grid.Column="0" Content="Name:"/>
    <Label Grid.Row="1" Grid.Column="0" Content="E-Mail:"/>
    <Label Grid.Row="2" Grid.Column="0" Content="Comment:"/>
    <TextBox Grid.Column="1" Grid.Row="0" Margin="3" />
    <TextBox Grid.Column="1" Grid.Row="1" Margin="3" />
    <TextBox Grid.Column="1" Grid.Row="2" Margin="3" />
    <Button Grid.Column="1" Grid.Row="3" HorizontalAlignment="Right" 
            MinWidth="80" Margin="3" Content="Send"  />
</Grid>

تغییر اندازه در سمت کد هم می‌تواند توسط کدهای صورت گیرد.
Auto sized GridLength.Auto
Star sized new GridLength(1,GridUnitType.Star)
Fixed size new GridLength(100,GridUnitType.Pixel)
مثال:
Grid grid = new Grid();
 
ColumnDefinition col1 = new ColumnDefinition();
col1.Width = GridLength.Auto;
ColumnDefinition col2 = new ColumnDefinition();
col2.Width = new GridLength(1,GridUnitType.Star);
 
grid.ColumnDefinitions.Add(col1);
grid.ColumnDefinitions.Add(col2);

قابلیت تغییر اندازه‌ی سطر و ستون توسط کاربر
یکی از تگ‌های ویژه داخل گری،د تگ Grid Splitter است. برای قرارگیری تگ splitter ابتدا باید یک سطر یا ستون بین سطر و ستون هایی که میخواهید از یکدیگر جدا شوند ایجاد کنید و اندازه‌ی آن را auto تعیین کنید و سپس مانند بقیه‌ی اشیا توسط Grid.Column یا Grid.Row مانند کد زیر تگ splitter را به آن اختصاص دهید.
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <Label Content="Left" Grid.Column="0" />
    <GridSplitter HorizontalAlignment="Right" 
                  VerticalAlignment="Stretch" 
                  Grid.Column="1" ResizeBehavior="PreviousAndNext"
                  Width="5" Background="#FFBCBCBC"/>
    <Label Content="Right" Grid.Column="2" />
</Grid>
خاصیت ResizeBehavior مشخص می‌کند که ستون یا سطرهای کناری کدام باید تغییر اندازه داشته باشند.
 BasedOnAlignment   مقدار پیش فرض این گزینه است و مشخص می‌کند سطر یا ستونی طرفی باید تغییر اندازه دهد که در Alignment آن آمده است
 CurrentAndNext   ستون یا سطر جاری  به همراه ستون یا سطر بعدی
 PreviousAndCurrent   ستون یا سطر جاری  به همراه ستون یا سطر قبلی
 PreviousAndNext   سطر یا ستون قبلی و بعدی که بهترین گزینه برای انتخاب است.

خاصیت ResizeDirection جهت تغییر اندازه را مشخص می‌کند که شامل سه مقدار Row,Column و Auto است که مقدار پیش فرض آن auto است و نیازی به ذکر آن نیست و خود سیستم میداند که باید تغییر اندازه در چه جهتی صورت بگیرد.


ساخت Custom Layout یا یک پنل سفارشی (اختصاصی)
در این دو قسمت، شما با پنل‌های متفاوتی آشنا شدید که قابلیت‌های مفیدی داشتند؛ ولی گاهی اوقات هیچ کدام از این‌ها به کار شما نمی‌آیند و دوست دارید پنلی داشته باشید که مطابق میل شما عمل کند. برای ساخت یک پنل سفارشی یک کلاس می‌سازیم که از کلاس Panel ارث بری می‌کند. در اینجا دو متد برای Override کردن وجود دارند:
MeasureOverride : تعیین اندازه پنل بر اساس اندازه تعیین شده برای المان‌های فرزند و فضای موجود.
ArrangeOverride: مرتب سازی المان‌ها در فضای موجود نهایی.

کد نمونه:
public class MySimplePanel : Panel
{
    // Make the panel as big as the biggest element
    protected override Size MeasureOverride(Size availableSize)
    {
        Size maxSize = new Size();
 
        foreach( UIElement child in InternalChildern)
        {
            child.Measure( availableSize );
            maxSize.Height = Math.Max( child.DesiredSize.Height, maxSize.Height);
            maxSize.Width= Math.Max( child.DesiredSize.Width, maxSize.Width);
        }
    }
 
    // Arrange the child elements to their final position
    protected override Size ArrangeOverride(Size finalSize)
    {
        foreach( UIElement child in InternalChildern)
        {
            child.Arrange( new Rect( finalSize ) );
        }
    }
}
لینک‌های زیر تعدادی از پنل‌های سفارشی پر طرفدار هستند که بر روی اینترنت به اشتراک گذاشته شده اند:
TreeMapPanel
Animating Tile Panel
Radial Panel
Element Flow Panel
Ribbon Panel

خواصی که باید در Layout‌ها با آنها بیشتر آشنا شویم:
Horizontal & Vertical Alignment
با دادن این خاصیت به کنترل‌های موجود، نحوه قرار گیری و موقعیت آن‌ها مشخص می‌گردد. جدول زیر بر ساس انواع موقعیت‌های مختلف تشکیل شده است:

Margin & Padding
این خاصیت‌ها حتما برای شما آشنا هستند. خاصیت margin فاصله کنترل از لبه‌های Layout است و خاصیت Padding فاصله محتویات کنترل از لبه‌های کنترل است.

Clipping
در صورتی که خاصیت ClipToBounds پنل برابر False باشند به این معناست که المان‌ها میتوانند از لبه‌های پنل خارج شوند، در صورتی که برابر True باشد مقدار خارج شده نمایش نمی‌یابد.

Scrolling
موقعیکه از پنلی استفاده می‌کنید که با تمام شدن ناحیه‌اش روبرو شده‌اید ولی کنترل‌های داخلش هنوز ادامه دارند، نیاز به یک اسکرول به شدت احساس می‌شود. در این حالت می‌توان از ScrollViewer استفاده کرد.
<ScrollViewer>
    <StackPanel>
        <Button Content="First Item" />
        <Button Content="Second Item" />
        <Button Content="Third Item" />
    </StackPanel>
</ScrollViewer>



نظرات مطالب
ارتقاء به ASP.NET Core 1.0 - قسمت 10 - بررسی تغییرات Viewها
در مطلب «ارتقاء به ASP.NET Core 1.0 - قسمت 11 - بررسی بهبودهای Razor» قسمت «نحوه‌ی سفارشی سازی کلاس پایه‌ی تمام Viewهای برنامه و معرفی inherits@ »، این مورد را توضیح دادم. برای نمونه اگر به فایل Views\_ViewStart.cshtml مراجعه کنید، یک چنین مقدار دهی عمومی در آن هست:
@{
    Layout = "_Layout";
}
این خاصیت عمومی Layout در کلاس پایه‌ی تمام ویووها تعریف شده‌است. اگر می‌خواهید معادل آن‌را داشته باشید، باید یک کلاس سفارشی پایه را با ارث بری از RazorPage ایجاد کنید:
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Localization;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Mvc.Razor.Internal;

namespace Core1RtmTestResources.StartupCustomizations
{
    public abstract class MyCustomBaseView<TModel> : RazorPage<TModel>
    {
        //روش خاص تزریق وابستگی‌ها در فایل ویژه‌ی جاری
        [RazorInject]
        public IHtmlLocalizerFactory MyHtmlLocalizerFactory { get; set; }

        public IHtmlLocalizer MySharedLocalizer => MyHtmlLocalizerFactory.Create(
            baseName: "SharedResource" /*مشخصات*/,
            location: "Core1RtmTestResources.ExternalResources" /*نام اسمبلی ثالث*/);

        public bool IsAuthenticated()
        {
            return Context.User.Identity.IsAuthenticated;
        }

#pragma warning disable 1998
        public override async Task ExecuteAsync()
        {
        }
#pragma warning restore 1998
    }
}
در اینجا چند نکته مهم هستند:
- در کلاس پایه‌ی سفارشی، امکان تزریق وابستگی‌ها در سازنده‌ی کلاس وجود ندارد. اما از طریق ویژگی RazorInject می‌توان این‌کار را انجام داد.
- RazorInject نیاز به نصب وابستگی ذیل را دارد:
{
    "dependencies": {
        //same as before
        "Microsoft.AspNetCore.Mvc.Razor": "1.0.0"
    }
}
- پس از تعریف این کلاس پایه، برای معرفی آن به فایل Views\_ViewImports.cshtml مراجعه کنید:
@using Core1RtmTestResources
@using Microsoft.AspNetCore.Mvc.Localization
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

@inherits Core1RtmTestResources.StartupCustomizations.MyCustomBaseView<TModel>
اکنون در تمام ویووهای برنامه به خاصیت عمومی MySharedLocalizer واقع در کلاس پایه‌ی سفارشی برنامه، دسترسی خواهید داشت:
MySharedLocalizer from MyCustomBaseView: @MySharedLocalizer["About Title"]
مطالب
Cookie - قسمت دوم

کوکی در جاوا اسکریپت 

همانطور که در قسمت قبل اشاره کوتاهی شد، مدیریت کوکی‌های در دسترس در وضعیت جاری، در جاوا اسکریپت ازطریق پراپرتی cookie از شی document امکان‌پذیر است. این پراپرتی کاری همانند هدرهای Set-Cookie و Cookie (که در قسمت قبل درباره آن‌ها بحث شد) انجام می‌دهد. این پراپرتی یک مورد کاملا استثنایی و نسبتا عجیب در زبان جاوا اسکریپت است. در نگاه اول ظاهرا document.cookie از نوع رشته است، اما قضیه کاملا فرق می‌کند. برای روشن شدن مطلب به ادامه بحث توجه کنید.

افزودن کوکی
- برای افزودن یا ویرایش یک کوکی باید از ساختاری مانند ساختار هدر Set-Cookie که چیزی شبیه به عبارت زیر است، پیروی کرد:
document.cookie = "name=value; expires=date; domain=theDomain; path=thePath; secure";
 
نکته: با توجه به توضیحاتی که در قسمت قبل ارائه شد، بدیهی است که امکان ثبت یک کوکی با فلگ HttpOnly در جاوا اسکریپت وجود ندارد!
 
اجرای دستوری شبیه با ساختار نشان داده شده در بالا، موجب حذف کوکی‌های قبلی نمی‌شود. از این دستور برای ایجاد یک کوکی و یا ویرایش یک کوکی موجود استفاده می‌شود. کوکی‌های ایجادشده با این روش تفاوتی با کوکی‌های ایجادشده توسط هدر Set-Cookie ندارند و همانند آنها در درخواست‌های بعدی با توجه به خواص تنظیم شده، به سمت سرور ارسال خواهند شد.
همانطور که مشاهده می‌کنید خاصیت‌های کوکی به صورت جفت‌های نام-مقدار درون یک رشته به document.cookie نسبت داده می‌شوند. این خاصیت‌ها توسط یک کاراکتر ; از یکدیگر جدا می‌شوند. شرح ساختار فوق در  زیر آورده شده است:
1. همیشه اولین جفتِ نام-مقدار همانند مثال بالا باید «عنوان و مقدار» کوکی را مشخص سازد. این قسمت تنها عضو اجباری ساختار فوق است.
2. سپس یک سمی‌کالن و یک فاصله
3. تاریخ انقضا (expires) یا حداکثر طول عمر کوکی (max-age)
4. سپس یک سمی‌کالن و یک فاصله
5. دمین و یا مسیر مربوط به کوکی
6. سپس یک سمی‌کالن و یک فاصله
7. سایر خواص چون Secure
نکته: این ساختار عجیب معرفی شده را عینا رعایت کنید. بقیه کار توسط مرورگر انجام خواهد شد.
نکته: قسمت‌های مختلف این ساختار case-sensitive نیست، البته به‌جز نام کوکی که کاملا case-sensitive است.
مثلا برای ثبت یک کوکی با عنوان myCookie و مقدار myValue و دمین d.com و مسیر test و طول عمر 5 روزه باید از دستور زیر استفاده کرد:
document.cookie = 'myCookie=myValue; max-age=432000; domain=d.com; path=/test';
 
خواندن کوکی
- برای خواندن کوکی‌ها تنها کافی است مقدار پراپرتی document.cookie بررسی شود. با اینکه از دستور نشان داده شده در بالا اینگونه برمی آید که پراپرتی document.cookie به رشته معرفی شده مقداردهی شده است، اما به محض خواندن این پراپرتی چیزی شبیه به عبارت زیر برگردانده میشود:
myCookie=myValue 
از بقیه خواص اثری نیست! این رفتار به دلیل حفط امنیت کوکی‌ها در تمام مرورگرها رعایت می‌شود.
- برای ثبت کوکی دیگری در وضعیت جاری کافی است یکبار دیگر دستور بالا را برای کوکی جدید به کار ببریم. مثلا به صورت زیر:
document.cookie = 'mySecondCookie=mySecondValue; path=/'
اینار یک کوکی سشنی بدون دمین و با مقدار / برای مسیر کوکی ثبت می‌شود! در این حالت کوکی قبلی دوباره نویسی و یا حذف نمی‌شود و تنها یک کوکی جدید به لیست کوکیهای مرورگر اضافه می‌شود! این رفتار عجیب از ویژگی‌های جالب document.cookie است.
- اگر مقدار document.cookie در این حالت خوانده شود مقدار زیر برگشت داده می‌شود:
myCookie=myValue; mySecondCookie=mySecondValue
باز هم خبری از سایر خاصیت‌ها نیست. ولی همانطور که می‌بینید کوکی دوم به لیست کوکی‌های مرورگر اضافه شده است.

نکته: عبارت برگشت داده شده از پراپرتی document.cookie همانند مقداری است که در هدر Cookie هر درخواست توسط مرورگر گنجانده می‌شود، یعنی جفت نام-مقدار کوکی‌ها به همراه یک ; و یک فاصله بین مقادیر هر کوکی. بنابراین برای بدست آوردن مقدار یک کوکی یکسری عملیات جهت Parse کردن داده‌های آن نیاز است!

متدها
امروزه کتابخانه‌های متعددی با استفاده از زبان جاوا اسکریپت برای برنامه نویسی سمت کلاینت وجود دارد که بیشتر آنها قابلیت‌هایی برای کار با کوکی‌ها نیز دارند. ازجمله می‌توان به jQuery و YUI اشاره کرد. پلاگین مخصوص کوکی‌ها در jquery در اینجا بحث شده است. برای کسب اطلاعات بیشتر درباره قابلیت‌های کار با کوکی در YUI نیز به اینجا مراجعه کنید. مطالب زیر صرفا برای روشن شدن بحث ارائه می‌شوند. بدیهی است که برای کارهای عملی بهتر است از کتابخانه‌های موجود استفاده شود.
با توجه به اطلاعات بالا از متدهای زیر می‌توان برای خواندن، افزودن و حذف کوکی‌ها استفاده کرد.

نکته: متدهای زیر از ترکیب چندین ریفرنس مختلف بدست آمده است. هرچند برای موارد خاص‌تر می‌توانند بیشتر سفارشی شوند.

افزودن و یا ویرایش کوکی
function setCookie(data, value) {
  if (typeof data === "string") {
    data = { name: data, value: value };
  };
  if (!data.name) throw "Cookie's name can not be null.";

  var cookie = escape(data.name) + "=" + escape(data.value);

  var expDate = null;
  if (data.expDays) {
    expDate = new Date();
    expDate.setDate(expDate.getDate() + data.expDays);
  }
  else if (data.expYear && data.expMonth && data.expDay) {
    expDate = new Date(data.expYear, data.expMonth, data.expDay);
  }
  else if (data.expires) {
    expDate = data.expires;
  }
  else if (data.maxAge) {
    expDate = new Date();
    expDate.setSeconds(expDate.getSeconds() + data.maxAge);
  }
  if (expDate != null) cookie += "; expires=" + expDate.toGMTString();

  if (data.domain)
    cookie += "; domain=" + escape(data.domain);

  if (data.path)
    cookie += "; path=" + escape(data.path);

  if (data.secure)
    cookie += "; secure";

  document.cookie = cookie;
  return document.cookie;
}
در کد فوق برای انکد کردن رشته‌های مورد استفاده از متد escape استفاده شده است. برای آشنایی با این متد به اینجا مراجعه کنید.
هم‌چنین کار کردن با نوع داده تاریخ در جاوا اسکریپت کمی متفاوت است. بنابراین برای آشنایی بیشتر با این نوع داده به اینجا رجوع کنید.
 
نکته: در متد بالا بدلیل عدم پشتیبانی از خاصیت max-age در نسخه‌های قدیمی اینترنت اکسپلورر (نسخه 8 و قبل از آن) تنها از خاصیت expires استفاده شده است.
 
نحوه استفاده از متد بالا به صورت زیر است:
setCookie('cookie1', 'Value1');
setCookie({name:'cookie1', value:'Value1'});
setCookie({name:'cookie2', value:'Value2', expDays:10});
setCookie({name:'cookie3', value:'Value3', expires:new Date()});
setCookie({name:'cookie4', value:'Value4', expYear:2013, expMonth:0, expDay:13});
setCookie({name:'cookie3', value:'Value3', maxAge:365*24*60*60});
setCookie({name:'cookie5', value:'Value5', domain:'d.net', path:'/'});
setCookie({name:'cookie6', value:'Value6', secure:true});
setCookie({name:'cookie7', value:'Value7', expDays:100, domain:'dd.com', path:'/employee', secure:true});
 
حذف کوکی
همانطور که در قسمت قبل هم اشاره شد، برای حذف یک کوکی، کافی است تا تاریخ انقضای آن به تاریخی در گذشته مقداردهی شود. بنابراین برای اینکار می‌توان از متد زیر استفاده کرد:
function delCookie(data) {
  if (typeof data === "string") {
    data = { name: data };
  };
  data.expDays = -1;
  return setCookie(data);
}
در متد فوق از متد setCookie که در بالا معرفی شد، استفاده شده است. نحوه استفاده از این متد هم به صورت زیر است:
delCookie('myCookie');
delCookie({ name: 'myCookie', domain: 'd.com', path: '/test' });
 
خواندن کوکی
برای خواندن مقدار یک کوکی می‌توان از متد زیر استفاده کرد:
function getCookie(name) {
  var cookies = document.cookie.split(";");
  for (var i = 0; i < cookies.length; i++) {
    var cookie = cookies[i].split("=");
    if (cookie[0].trim() == escape(name)) {
      return unescape(cookie[1].trim());
    }
  }
  return null;
}
برای آشنایی با متد unescape که در بالا از آن استفاده شده است به اینجا مراجعه کنید. در متد فوق از متد trim زیر استفاده شده است:
String.prototype.trim = function () {
  return this.replace(/^\s+|\s+$/g, "");
};
String.prototype.trimStart = function () {
  return this.replace(/^\s+/, "");
};
String.prototype.trimEnd = function () {
  return this.replace(/\s+$/, "");
};
این متدها از اینجا گرفته شده است.
روش استفاده شده برای خواندن مقادیر کوکی‌ها در متد بالا بسیار ساده و ابتدایی است و صرفا برای آشنایی با نحوه Parse کردن رشته برگشت داده شده توسط document.cookie ارائه شده است. روش‌های مناسب‌تر و مطمئن‌تر با یک جستجوی ساده در دسترس هستند. البته همانطور که قبلا هم اشاره شد، استفاه از کتابخانه‌های موجود راه‌حل بهتری است.
هم‌چنین ازآنجاکه مقدار یک کوکی می‌تواند شامل کاراکتر = نیز باشد، بنابراین قسمت return متد فوق را می‌توان به صورت زیر تغییر داد:
cookie.shift(1);
return unescape(cookie.join('=').trim());
 
نکته: با توجه به مطالب ارائه شده در قسمت قبل  بدست آوردن مقادیر کوکی‌ها کمی پیچیده‌تر از دیگر عملیات‌هاست. ازآنجاکه راه مستقیمی با استفاده از جاوا اسکریپت برای یافتن سایر خواص کوکی وجود ندارد، بنابراین بدست آوردن مقدار دقیق کوکی موردنظر ممکن است غیرممکن باشد! (با توجه به اینکه کوکی‌های متفاوت می‌توانند نام‌های یکسانی داشته باشند).
 
با توجه به نکته بالا، حال اگر با یک نام بخصوص، چندین کوکی ثبت شده باشد (با خواص متفاوت)، یکی از راه‌حل‌ها این است که آرایه‌ای از مقادیر این کوکی‌های همنام برگشت داده شود. بنابراین متد فوق را می‌توان به صورت زیر تکمیل کرد:
function getCookie(name) {
  var foundCookies = [];
  var cookies = document.cookie.split(";");
  for (var i = 0; i < cookies.length; i++) {
    var cookie = cookies[i].split("=");
    if (cookie[0].trim() == escape(name) && cookie.length >= 2) {
      cookie.shift(1);
      foundCookies.push(unescape(cookie.join('=').trim()));
    }
  }
  return foundCookies.length > 1 
            ? foundCookies
            : foundCookies.length == 1
                ? foundCookies[0]
                : null;
}

خلاصه‌ای از نحوه استفاده از متدهای بالا در IE8 (برای نمایش اجرای درست در مرورگری قدیمی!) در تصویر زیر  نشان داده شده است:

 
نکته: کار توسعه این متدها را میتوان برای پشتیبانی از SubCookieها نیز ادامه داد، اما به دلیل دورشدن از مبحث اصلی، این موضوع در این مطلب ارائه نمیشود (درباره این نوع از کوکی‌ها در قسمت قبل شرح کوتاهی داده شده است). اگر علاقه‌مند و نیازمند به این نوع کوکی‌ها هستید، کتابخانه YUI پشتیبانی کاملی از آنها ارائه میکند.
 
در قسمت بعدی به نکات کار با کوکی در ASP.NET میپردازیم.

منابع:
نظرات اشتراک‌ها
توسعه Asp.net Core و Asp.net Core Identity
در لایه سرویس، ارث بری‌های دو سرویس ذیل را باید به صورت زیر تغییر دهید:
public class ApplicationRoleStore :
        RoleStore<Role, ApplicationDbContext, int, UserRole, RoleClaim>,
        IApplicationRoleStore


public class ApplicationUserStore :
        UserStore<User, Role, ApplicationDbContext, int, UserClaim, UserRole, UserLogin, UserToken, RoleClaim>,
        IApplicationUserStore
بعد از آن تمام سازنده‌های مورد نیاز کلاس‌های لایه سرویس باید جهت تزریق و استفاده‌ی از اینترفیس‌های همین لایه تغییر کنند.

پ.ن.
این مورد بحث «بسیار» مفصلی هست که اینجا امکانش نیست و حتما نیاز به ارائه‌ی یک solution کامل دارد تا قابل درک باشد: «سفارشی سازی ASP.NET Core Identity - قسمت اول - موجودیت‌های پایه و DbContext برنامه »
نظرات مطالب
React 16x - قسمت 27 - احراز هویت و اعتبارسنجی کاربران - بخش 2 - استخراج و نمایش اطلاعات JWT و خروج از سیستم
JWT یک مکانیزم به اصطلاح self-contained را ارائه میدهد و همانطور که اشاره شده است پیاده‌سازی عملیات Logout منطقی نیست چون توکنی که صادر میشود دارای یک تاریخ انقضاء است بنابراین کلاینت تا زمان در اختیار داشتن توکن و همچنین معتبر بودن توکن میتواند از آن استفاده کند؛ این self-contained بودن در واقع باعث خواهد شد که دیگری نیازی به داشتن database call برای بررسی معتبر بودن توکن نباشد. در نهایت اگر خواستید میتوانید یک لایه دیگر به سیستم اضافه کنید و Logout را پیاده‌سازی کنید (قسمت تهیه یک اعتبارسنج توکن سفارشی  در مطلبی که لینک دادید) این لایه میتواند دیتابیس باشد یا یک چیزی مانند Redis؛