اشتراک‌ها
درز اطلاعات شناسنامه ای میلیونها ایرانی از سازمان ثبت احوال

در ادامه افشای اطلاعات کاربران فضای مجازی طی روزهای اخیر که مربوط به لو رفتن اطلاعات کاربران نسخه غیررسمی اپلیکیشن تلگرام و یکی از بازارهای ایرانی نرم افزارهای آیفون می‌شد، شب گذشته نیز یک ربات تلگرامی، اطلاعات شناسنامه ای ۸۰ میلیون ایرانی را از طریق درج کد ملی هر شخص، در اختیار کاربران قرار داده است. ظاهرا تمامی دیتابیس سازمان ثبت احوال کپی برداری شده است و هکرهای آن مدعی فروش آن به ازای 10 بیت کوین شده اند.

درز اطلاعات شناسنامه ای میلیونها ایرانی از سازمان ثبت احوال
مطالب
خلاصه‌ای در مورد روش‌های دریافت فایل از سایت NuGet
بهبود سرعت دریافت بسته‌های نیوگت

در کشور بسیاری از اوقات دسترسی به پروتکل HTTPS به کندی صورت می‌گیرد. گاهی از اوقات نیز این دسترسی غیر ممکن می‌شود تا حد دریافت چند بایت در دقیقه. همین مساله تاکنون بر روی بسیاری از مسایل دیگر نیز تاثیر گذار بوده است؛ برای مثال اگر یک مخزن کد را مثلا در CodePlex یا GitHub داشته باشید، چون تمام Commitها از طریق همین پروتکل امن صورت می‌گیرد، کار کردن با آن‌ها بسیار مشکل خواهد شد. نمونه‌ی دیگر آن دسترسی به NuGet است. فید NuGet در VS.NET به Https تنظیم شده است. اگر دسترسی به Https برای شما به کندی صورت می‌گیرد فقط کافی است مسیر فید آن‌را در منوی Tools، گزینه‌ی Options، ذیل قسمت Package manager یافته و به http://nuget.org/api/v2 تغییر دهید؛ یعنی به Http خالی، بجای Https؛ تا سرعت دریافت بسته‌های NuGet مورد نظر افزایش یابند.


دریافت مستقیم بسته‌های نیوگت

برای دریافت بسته‌های نیوگت که دارای پسوند nupkg هستند، اما در اصل یک فایل zip بیشتر نیستند، الزامی به استفاده از ابزار و افزونه نیوگت در VS.NET نیست. می‌توان این بسته‌ها را به صورت مستقیم نیز دریافت کرد. برای مثال اگر آدرس بسته‌ای در سایت NuGet به صورت زیر است:
https://www.nuget.org/packages/PropertyChanged.Fody
برای دریافت مستقیم آن کافی است آدرس ذیل را درخواست کنید:
https://www.nuget.org/api/v2/package/PropertyChanged.Fody/1.42.0
یک api/v2 به این لینک اضافه می‌شود به همراه شماره نگارش مدنظر برای دریافت:
 https://www.nuget.org/api/v2/package/{packageID}/{packageVersion}
و یا برای مثال در سایت نیوگت عضو شوید و سپس به آن لاگین کنید. به این ترتیب با مراجعه به هر کتابخانه‌ای که در آنجا آپلود شده، یک لینک download در کنار صفحه، سمت چپ ظاهر می‌شود. با کلیک بر روی آن فایل nupkg آن کتابخانه قابل دریافت خواهد بود. این فایل در حقیقت یک فایل zip است. بنابراین کار کردن با محتویات آن ساده‌است.
به صورت خلاصه:
لینک اصلی کتابخانه: https://www.nuget.org/packages/Twitter.Bootstrap.RTL.Less/3.0.0
لینک دانلود آن: https://www.nuget.org/api/v2/package/Twitter.Bootstrap.RTL.Less/3.0.0

راه دیگر، ساخت دستی این آدرس است:
https://az320820.vo.msecnd.net/packages/propertychanged.fody.1.42.0.nupkg
که در حقیقت تشکیل شده است از:
 https://az320820.vo.msecnd.net/packages/{name}.{version}.nupkg
اگر نام آخرین بسته ارسالی PropertyChanged.Fody 1.42.0 باشد. فقط کافی است این دو قسمت را، یعنی نام و شماره نگارش را با یک نقطه به هم متصل کنید و سپس به انتهای آن، پسوند nupkg را اضافه نمائید. این فایل در آدرس https://az320820.vo.msecnd.net/packages/ به صورت مستقیم قابل دریافت است.


اهمیت تنظیمات IE

اگر پیام قطع شدن اتصال یا مشکلات DNS را در کنسول NuGet در VS.NET دریافت می‌کنید، ابتدا سعی کنید همان روش ذکر شده در ابتدای بحث را امتحان کنید. اگر کار نکرد احتمالا مشکل از تنظیمات IE است. برای مثال اگر بر روی تنظیمات اتصالی شما در IE یک پروکسی غیرقابل دسترسی در زمان جاری، تنظیم شده باشد، این مساله مستقیما بر روی اتصالات برنامه‌های دات نتی نیز تاثیر گذار است. بنابراین ابتدا لینک nupkg را که ساخته‌اید یکبار با IE امتحان کنید. اگر قابل دریافت نبود یعنی تنظیمات آن به هم ریخته است و این مساله بر روی بسیاری از برنامه‌های دیگر نیز تاثیر گذار است.
مطالب
طراحی شیء گرا: OO Design Heuristics - قسمت دوم

در قسمت اول با مفاهیم اولیه Class و Object آشنا شدیم.

Messages and Methods

Objectها باید مانند ماشین‌هایی تلقی شوند که عملیات موجود در واسط عمومی خود را برای افرادی که درخواست مناسبی ارسال کنند، اجرا خواهند کرد. با توجه به اینکه یک object از استفاده کننده خود مستقل است و وابستگی به او ندارد و همچنین توجه به ساختار نحوی (syntax) برخی از زبان‌های شیء گرای جدید، عبارت «sending a message» برای توصیف اجرای رفتاری از مجموعه رفتارهای object، استفاده میشود.
به محض اینکه پیغامی (Message) به سمت object ارسال شود، ابتدا باید تصمیم بگیرد که این پیغام ارسالی را درک می‌کند. فرض کنیم این پیغام قابل درک است. در این صورت object مورد نظر، همزمان با نگاشت پیغام به یک فراخوانی تابع (function call)، خود را به صورت ضمنی به عنوان اولین آرگومان ارسال می‌کند. تصمیم گرفتن در رابطه با قابل درک بودن یک پیغام، در زبان‌های مفسری در زمان اجرا و در زبان‌های کامپایلری در زمان کامپایل، انجام میگرد. 
نام (یا prototype) رفتار یک وهله، Message (پیغام) نامیده می‌شود. بسیاری از زبان‌های شیء گرا مفهموم Overloaded Functions Or Operators را پشتیبانی می‌کنند. در این صورت می‌توان در سیستم دو تابعی داشت که با نام یکسان، یا انواع مختلف آرگومان (intraclass overloading) داشته باشند یا در کلاس‌های مختلفی (interclass overloading) قرار گیرند. 
ممکن است کلاس ساعت زنگدار، دو پیغام set_time که یکی از آنها با دو آرگومان از نوع عدد صحیح و دیگری یک آرگومان رشته‌ای است داشته باشد.

void AlarmClock::set_time(int hours, int minutes); 

void AlarmClock::set_time(String time);

در مقابل، کلاس ساعت زنگدار و کلاس ساعت مچی هر دو messageای به نام set_time با دو آرگومان از نوع عدد صحیح دارند.

void AlarmClock::set_time(int hours, int minutes); 

void Watch::set_time(int hours, int minutes);

باید توجه کنید که یک پیغام، شامل نام تابع، انواع آرگومان، نوع بازگشتی و کلاسی که پیغام به آن متصل است، می‌باشد. این اطلاعاتی که مطرح شد، بخش اصلی چیزی است که کاربر یک کلاس نیاز دارد در مورد آن‌ها آگاهی داشته باشد. 

در برخی از زبان‌ها و یا سیستم‌ها، اطلاعات دیگری مانند: انواع استثناءهایی که از سمت پیغام پرتاب می‌شوند تا اطلاعات همزمانی (پیغام به صورت همزمان است یا ناهمزمان) را برای استفاده کننده مهیا کنند. از طرفی پیاده سازی کنندگان یک کلاس باید از پیاده سازی پیغام آگاه باشند. جزئیات پیاده سازی یک پیغام -کدی که پیغام را پیاده سازی می‌کند- Method (متد) نامیده میشود. آنگاه که نخ (thread) کنترل درون متد باشد، برای مشخص کردن اینکه پیغام رسیده برای کدام وهله ارسال شده‌است، ارجاعی به وهله مورد نظر و به عنوان اولین آرگومان، به صورت ضمنی ارسال می‌شود. این آرگومان ضمنی، در بیشتر زبان‌ها Self Object نامیده می‌شود (در سی پلاس پلاس this object نام دارد). در نهایت، مجموعه پیغام‌هایی که یک وهله می‌تواند به آنها پاسخ دهد، Protocol (قرارداد) نام دارد.

دو پیغام خاصی که کلاس‌ها یا وهله‌ها می‌توانند به آنها پاسخ دهند، اولی که استفاده کنندگان کلاس برای ساخت وهله‌ها از آن استفاده می‌کنند، Constructor (سازنده) نام دارد. هر کلاسی می‌تواند سازنده‌های متعددی داشته باشد که هر کدام مجموعه پارامترهای مختلفی را برای مقدار دهی اولیه می‌پذیرند. دومین پیغام، عملیاتی است که وهله را قبل از حذف از سیستم، پاک سازی می‌کند. این عملیات، Destructor (تخریب کننده) نام دارد. بیشتر زبان‌های شیء گرا، برای هر کلاس تنها یک تخریب کننده دارند. این پیغام‌ها را به عنوان مکانیزم مقدار دهی اولیه و پاک سازی در پارادایم شیء گرا در نظر بگیرید.

قاعده شهودی 2.2

استفاده کنندگان از کلاس باید به واسط عمومی آن وابسته باشند، اما یک کلاس نباید به استفاده کنندگان خود، وابسته باشد. (Users of a class must be dependent on its public interface, but a class should not be dependent on its users)

منطق پشت این قاعده، یکی از شکل‌های قابلیت استفاده مجدد (resuability) می‌باشد. یک ساعت زنگدار ممکن است توسط شخصی در اتاق خواب او استفاده شود. واضح است که شخص مورد نظر به واسط عمومی ساعت زنگدار وابسته می‌باشد. به هر حال، ساعت زنگدار نباید به شخصی وابسته باشد. اگر ساعت زنگدار به شخصی وابسته باشد، بدون مهیا کردن یک شخص، نمی‌توان از آن برای ساخت یک TimeLockSafe استفاده کرد. این وابستگی‌ها برای مواقعیکه می‌خواهیم امکان این را داشته باشیم تا کلاس ساعت زنگدار را از دامین (domain) خود خارج کرده و در دامین دیگری، بدون وابستگی هایش مورد استفاده قرار دهیم، نامطلوب هستند.

شکل 2.4 The Use Of Alarm Clocks

 The Use Of Alarm Clocks قاعده شهودی 2.3

تعداد پیغام‌های موجود در قرارداد یک کلاس را کمینه سازید. (Minimize the number of messages in the protocol of a class)

چندین سال قبل، مطلبی منتشر شد که کاملا متضاد این قاعده شهودی می‌باشد. طبق آن، پیاده سازی کننده یک کلاس می‌تواند یکسری عملیات را با فرض اینکه در آینده مورد استفاده قرار گیرند، برای آن در نظر بگیرد. ایراد این کار چیست؟ اگر شما از این قاعده پیروی کنید، حتما کلاس LinkedList من، توجه شما را جلب خواهد کرد؛ این کلاس در واسط عمومی خود 4000 عملیات را دارد. فرض کنید قصد ادغام دو وهله از این کلاس را داشته باشید. در این صورت حتما فرض شما این است که عملیاتی تحت عنوان merge در این کلاس تعبیه شده است. بعد از جستجوی بین این تعداد عملیات، در نهایت این عملیات خاص را پیدا نخواهید کرد. چراکه این عملیات متأسفانه به صورت یک overloaded plus operator پیاده سازی شده است. مشکل اصلی واسط عمومی با تعداد زیادی عملیات این است که فرآیند یافتن عملیات مورد نظرمان را خیلی سخت یا حتی ناممکن خواهد کرد و مشکلی جدی برای قابلیت استفاده مجدد تلقی می‌شود.

با کمینه نگه داشتن تعداد عملیات واسط عمومی، سیستم، قابل فهم‌تر و همچنین مولفه‌های (components) آن به راحتی قابل استفاده مجدد خواهند بود.

قاعده شهودی 2.4

پیاده سازی یک واسط عمومی یکسان کمینه برای همه کلاس‌ها  (Implement a minimal public interface that all classes understand [e.g., operations such as copy (deep versus shallow), equality testing, pretty printing, parsing from an ASCII description, etc.].)

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

به عنوان مثال کلاس Object در دات نت به عنوان کلاس پایه ضمنی با یکسری از متدهای عمومی (برای مثال ToString)، نشان دهنده تعریف یک واسط عمومی مشترک برای همه کلاس‌ها در این فریمورک، می‌باشد.

public class Object
    {
        public Object();
        public static bool Equals(Object objA, Object objB){...}
        public static bool ReferenceEquals(Object objA, Object objB){...}
        public virtual bool Equals(Object obj){...}
        public virtual int GetHashCode(){...}
        public Type GetType(){...}
        public virtual string ToString(){...}
        protected Object MemberwiseClone(){...}
    }


قاعده شهودی 2.5 

جزئیات پیاده سازی، مانند توابع خصوصی common-code  ( توابعی که کد مشترک سایر متدهای کلاس را در بدنه خود دارند) را در واسط عمومی یک کلاس قرار ندهید.  (Do not put implementation details such as common-code private functions into the public interface of a class)

این قاعده برای کاهش پیچیدگی واسط عمومی کلاس برای استفاده کنندگان آن، طراحی شده است. ایده اصلی این است که استفاده کنندگان کلاس تمایلی ندارند به اعضایی دسترسی داشته باشند که از آنها استفاده نخواهند کرد؛ این اعضا باید به صورت خصوصی در کلاس قرار داده شوند. این توابع خصوصی common-code، زمانیکه متدهای یک کلاس، کد مشترکی را داشته باشند، ایجاد خواهند شد. قرار دادن این کد مشترک در یک متد، معمولا روش مناسبی می‌باشد. نکته قابل توجه این است که این متد، عملیات جدیدی نمی‌باشد؛ بله جزئیات پیاده سازی دو عملیات دیگر از کلاس را ساده کرده است.

شکل 2.5  Example of a common-code private function

Example of a common-code private function

مثال واقعی

فرض کنید در شکل بالا، کلاس X معادل یک LinkedList کلاس، f1و f2 به عنوان توابع insert و remove و تابع f به عنوان تابع common-code که عملیات یافتن آدرس را برای درج و حذف انجام می‌دهد، می‌باشند.

قاعده شهودی 2.6

واسط عمومی کلاس را با اقلامی که یا استفاده کنندگان از کلاس توانایی استفاده از آن را نداشته و یا تمایلی به استفاده از آنها ندارند، آمیخته نکنید.  (Do not clutter the public interface of a class with items that users of that class are not able to use or are not interested in using )

 این قاعده شهودی با قاعده قبلی که با قرار دادن تابع common-code در واسط عمومی کلاس، فقط باعث در هم ریختن واسط عمومی شده بود، مرتبط می‌باشد. در برخی از زبان‌ها مانند C++‎، برای مثال این امکان وجود دارد که سازنده یک کلاس انتزاعی (abstract) را در واسط عمومی آن قرار دهید؛ حتی با وجود اینکه در زمان استفاده از آن سازنده با خطای نحوی روبرو خواهید شد. این قاعده شهودی کلی، برای کاهش این مشکلات در نظر گرفته شده است. 

مطالب
دانلود مجوز SSL یک سایت HTTPS
اگر به مرورگرها دقت کرده باشید، امکان نمایش SSL Server Certificate یک سایت استفاده کننده از پروتکل HTTPS را دارند. برای مثال در فایرفاکس اگر به خواص یک صفحه مراجعه کنیم، در برگه امنیت آن، امکان مشاهده جزئیات مجوز SSL سایت جاری فراهم است:



سؤال: چگونه می‌توان این مجوزها را با کدنویسی دریافت یا تعیین اعتبار کرد؟

قطعه کد زیر، نحوه دریافت مجوز SSL یک سایت را نمایش می‌دهد:
using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Security.Cryptography.X509Certificates;

namespace DownloadCerts
{
    class Program
    {
        static void Main(string[] args)
        {
            // صرفنظر از خطاهای احتمالی مجوز
            ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };

            var url = "https://pdfreport.codeplex.com";
            var request = WebRequest.Create(url) as HttpWebRequest;
            request.Method = WebRequestMethods.Http.Head;
            using (var response = request.GetResponse())
            { /* در اینجا مجوز، در صورت وجود دریافت شده */  }

            if (request.ServicePoint.Certificate == null)
                return;

            // ذخیره سازی مجوز در فایل
            var cert = new X509Certificate2(request.ServicePoint.Certificate);
            Console.WriteLine("Expiration Date: {0}", cert.GetExpirationDateString());
            var data = cert.Export(X509ContentType.Cert);
            File.WriteAllBytes("site.cer", data);

            Process.Start(Environment.CurrentDirectory);
        }
    }
}
ممکن است مجوز یک سایت معتبر نباشد. کلاس WebRequest در حین مواجه شدن با یک چنین سایت‌هایی، یک WebException را صادر می‌کند. از این جهت که می‌خواهیم حتما این مجوز را دریافت کنیم، بنابراین در ابتدای کار، ServerCertificateValidation را غیرفعال می‌کنیم.
سپس یک درخواست ساده را به آدرس سرور مورد نظر ارسال می‌کنیم. پس از پایان درخواست، خاصیت request.ServicePoint.Certificate با مجوز SSL یک سایت مقدار دهی شده است. در ادامه نحوه ذخیره سازی این مجوز را با فرمت cer مشاهده می‌کنید.


نظرات مطالب
احراز هویت و اعتبارسنجی کاربران در برنامه‌های Angular - قسمت چهارم - به روز رسانی خودکار توکن‌ها
در صورتی که نرم افزار در بیش از یک tab/window باز باشد ممکن است race condition به وجود بیاید. البته متوجه هستم این مقاله صرفا یک مثال آموزشی هست. برای جلوگیری از ارسال درخواست همزمان جهت بروزرسانی token چه راه حلی پیشنهاد میشه؟ 
این راه حل خوبه؟ استفاده از localStorage و آگاه سازی دیگر نسخه‌های در حال اجرا یک درخواست پیش از این برای بروزرسانی ارسال شده/درحال ارسال است.
مطالب
ایجاد ابزارهای سراسری ویژه NET Core.
از زمان ارائه نگارش net core 2.1.، ابزارهای سراسری (Global tools) نیز معرفی شدند. استفاده از این ابزارها در محیط cli در جهت آسان‌تر شدن و سریعتر شدن وظایف، صورت می‌پذیرد. net core sdk. مربوطه، تمامی امکانات لازم از جهت ایجاد، حذف و به روزرسانی ابزارها را از طریق nuget شامل می‌گردد. تعداد بسیار زیادی از این ابزارها در حال حاضر ایجاد شده‌اند که در لیست زیر، تعدادی از آن‌ها را معرفی میکنیم و سپس به نحوه‌ی ایجاد این نوع ابزارها میپردازیم.
  • dotnet-ignore : این ابزار جهت دریافت فایل‌های gitignore. کاربرد داشته و از یک مخزن عمومی گیت هاب جهت دریافت این فایل‌ها استفاده میکند. این مخزن شامل انواع قالب‌های gitignore در پروژه‌های متفاوت میباشد. با استفاده از این ابزار، ایجاد فایل gitignore راحت‌تر و سریعتر امکانپذیر میباشد.
  • dotnet-serve : میزبانی و نمایش لیست فایل‌های استاتیک محلی و اجرای آن‌ها را در بستر http، فراهم مینماید.
  • dotnet-cleanup : جهت پاکسازی محیط بیلد مانند دایرکتوری‌های bin و obj میباشد. همان کار گزینه clean در منوی بیلد را بازی میکند.
  • dotnet-warp : این ابزار در واقع پروژه Warp است که برای ایجاد یک تک فایل اجرایی جهت انتقال راحت‌تر فایل پروژه صورت میگیرد که همه وابستگی‌های آن در همان تک فایل قرار میگیرد.
  • Amazon.ECS.Tools Amazon.ElasticBeanstalk.Tools  و  Amazon.Lambda.Tools  : این ابزارها که به صورت رسمی از طرف آمازون ارائه شده‌اند که جهت deploy شدن راحت‌تر پروژه به محیط‌های توسعه وب آمازون مورد استفاده قرار میگیرند.
جهت مشاهده لیست کامل این ابزارها، به این مخزن گیت هاب مراجعه نمایید. نام ابزار و همچنین لینک‌ها و توضیحات هر کدام، در این مخزن موجود است. همچنین جهت اضافه شدن ابزاری که در لیست نیست، از طریق ایجاد issue یا pull request لیست را به روزرسانی نمایید.

نحوه‌ی نصب، حذف و به روزرسانی ابزارهای سراسری
جهت نصب یک ابزار، از دستور زیر استفاده میکنیم:
dotnet tool install -g dotnet-ignore
سوییچ g به معنای نصب سراسری ابزار و افزوده شدن آن به متغیرهای محیطی PATH میباشد که به راحتی در هر مسیری از محیط کنسول در دسترس خواهد بود و به مسیر dotnet/tools/. محدود نخواهد بود.
جهت مشاهده لیست تمامی ابزاهای سراسری نصب شده بر روی سیستم میتوانید از کامند زیر استفاده نمایید:
dotnet tool list -g
نحوه به روزرسانی ابزار و ارتقا آن به آخرین نسخه پایدار، با دستور زیر میباشد:
dotnet tool update -g dotnet-ignore
دستور حذف:
dotnet tool uninstall -g dotnet-ignore

ایجاد یک ابزار سراسری
جهت ساخت یک ابزار سراسری نیاز است تا یک پروژه را از نوع کنسول ایجاد نمایید و سپس به فایل csproj، خطوط زیر را اضافه کنید:
<PropertyGroup>
    <PackAsTool>true</PackAsTool>
    <ToolCommandName>dotnet-mytool</ToolCommandName>
    <PackageOutputPath>./nupkg</PackageOutputPath>
</PropertyGroup>
گزینه PackAsTool، امکان تبدیل فایل اجرایی شما را به یک ابزار سراسری فراهم میکند. دو گزینه بعدی که اختیاری است، به ترتیب شامل نام ابزار سراسری است که در صورت ذکر نشدن نام فایل پروژه، بدون پسوند csproj. میباشد و سومین مورد نیز مسیر قرارگیری فایل ابزار سراسری به عنوان یک بسته nuget میباشد.
جهت ساخته شدن فایل، ابتدا یکبار پروژه را بیلد کرده و پس از اجرای دستور dotnet pack، فایل پکیج در مسیر ذکر شده ساخته میشود و آماده انتقال به مخازن nuget میباشد. جهت تست و اجرای ابزار بر روی سیستم خود قبل از عرضه نهایی نیاز است تا با دستور زیر آن را بر روی سیستم خود نصب و آزمایش نمایید:
dotnet tool install --global --add-source ./nupkg globaltools
سوییچ global که در بالاتر نیز توضیح داده شد، باعث نصب سراسری ابزار میگردد و سوییچ add-source که بعد از آن مسیر فایل ابزار، آمده است، به این معنا است که به صورت موقت، این دایرکتوری یا مسیر را به عنوان مخزن nuget  شناسایی کرده تا امکان یافتن بسته در آن مسیر مهیا گردد و سپس نام پروژه در پایان ذکر میگردد. در آخر جهت اطمینان از نصب میتوانید ابزار را صدا بزنید:
dotnet-mytool
با توجه به اینکه اصل مطلب گفته در رابطه با ایجاد یک ابزار سراسری در اینجا به پایان میرسد، ولی ایجاد یک ابزار خط فرمانی نیازمند یک سری کدنویسی‌ها جهت ایجاد کامندها و سوییچ‌ها و راهنمای مربوط به آن نیز میباشد. بدین جهت کتابخانه زیر را نصب نمایید:
https://www.nuget.org/packages/McMaster.Extensions.CommandLineUtils
این کتابخانه شامل کلاس هایی جهت ایجاد یک ابزار خط فرمانی راحت‌تر میباشد.

ایجاد یک ابزار عمومی جهت یادداشت نویسی
برای استفاده از این کتابخانه، یک پروژه از نوع کنسول را با نام globaltools ایجاد نمایید و کتابخانه‌ی بالا را نصب نمایید. سپس به ازای هر کامند، یک کلاس را ایجاد میکنیم. ابتدا جهت ایجاد کامندی با نام NewNote یک کلاس را به همین نام میسازیم:
[Command(Description="Add a new note")]
    public class NewNote
    {
        [Required]
        [Option(Description="title of note")]
        public string Title{ get; set; }

        [Option(Description="content of note")]
        public string Body{ get; set; }
    }
با مزین کردن کلاس به ویژگی command، این کلاس را یک کامند معرفی کرده و شرحی از کاری که این کامند را انجام میدهد، نیز وارد می‌کنیم. این شرح بعدا در ابزار تولید شده به عنوان متن راهنما به کار می‌رود. سپس پراپرتی‌هایی را که با ویژگی option مزین گشته‌اند، به عنوان سوییچ معرفی میکنیم. همچنین میتوان از DataAnotation‌ها نیز جهت اعتبار سنجی نیز استفاده نمود. 
بعد از ایجاد موارد بالا، نیاز است که اکشنی که باید این کامند را اجرا کند، به آن اضافه کرد. جهت افزودن این اکشن، یک متد را با نام OnExecute، به بدنه این کلاس اضافه می‌کنیم:
[Command(Description="Add a new note")]
    public class NewNote:BaseClass
    {
        [Required]
        [Option(Description="title of note")]
        public string Title{ get; set; }

        [Option(Description="content of note")]
        public string Body{ get; set; }

        public void OnExecute(IConsole console)
        {

            var dir = GetBaseDirectory();
            if(!Directory.Exists(dir))
            {
                Directory.CreateDirectory(dir);
            }
            var filePath = Path.Combine(dir, Title + ".txt");
            File.WriteAllText(filePath, Body);
            console.WriteLine("the note is saved");
        }
    }
در پارامتر این متد، یک اینترفیس با نام IConsole جهت ارتباط با محیط کنسول دیده میشود که در پایان عملیات، پیام «یادداشت ذخیره شد» توسط آن چاپ میگردد. کار این متد به طور خلاصه این است که مسیر اجرایی ابزار جاری را دریافت کرده و سپس در یک دایرکتوری با نام notes، برای هر یادداشت یک فایل ایجاد شده و محتوای دریافتی از کاربر داخل آن قرار میگرد و نام هر فایل، موضوع یادداشتی است که کاربر وارد کرده‌است. متد GetBaseDirectory که مسیر ذخیره یادداشت‌ها را بر میگرداند، در کلاس BaseClass با محتوای زیر قرار گرفته است:
public class BaseClass
    {
        protected string GetBaseDirectory(){
            var baseDirectory = Environment.CurrentDirectory;
            return (Path.Combine(baseDirectory, "notes"));
        }
    }

کامند بعدی، لیست یادداشت‌های ثبت شده‌است:
public class List:BaseClass
    {
        [Option(Description="search a phrase in notes title")]
        public string Grep{ get; set; }
        public void OnExecute(IConsole console)
        {
            try
            {
                var baseDirectory = GetBaseDirectory();

                var dir = new DirectoryInfo(baseDirectory);
                var files = dir.GetFiles();
                foreach(var file in files)
                {
                    if(!String.IsNullOrEmpty(Grep) && !file.Name.Contains(Grep))
                        continue;

                    console.WriteLine(Path.GetFileNameWithoutExtension(file.Name));
                }
            }
            catch (Exception e)
            {
                console.WriteLine(e.Message);
            }
        }
    }
کار این کلاس، بازگردانی لیستی از یادداشت‌های ثبت شده است که حاوی سوییچ grep برای فیلتر کردن اسامی یادداشت هاست.
کلاس بعدی show نیز جهت نمایش کلاس بر اساس عنوان یادداشت است:
[Command(Description="show contnet of note")]
    public class Show:BaseClass
    {
        [Required]
        [Option(Description="title of note")]
        public string Title{ get; set; }


        public void OnExecute(IConsole console){
            var baseDirectory = GetBaseDirectory();
            var file = Path.Combine(baseDirectory, Title+".txt");

            if(!File.Exists(file))
            {
                console.WriteLine("The Note NotFound...");
                return;
            }
            console.WriteLine(File.ReadAllText(file));

        }
    }
در صورتیکه یادداشت مورد نظر وجود نداشته باشد، با پیام The Note NotFound کار به پایان میرسد.
بعد از اتمام کامندهای مربوطه، به کلاس program رفته و برای آن نیز ویژگی command را اضافه می‌کنیم و همچنین ویژگی subCommand را جهت معرفی کامندهایی که در برنامه در دسترس کاربر قرار میگیرند، اضافه میکنیم:
    [Command(Description="An Immediate Note Saver")]
    [Subcommand(typeof(NewNote),typeof(List),typeof(Show))]
    class Program
    {
        static int Main(string[] args)
        {
            return CommandLineApplication.Execute<Program>(args);
        }

        public int OnExecute(CommandLineApplication app, IConsole console)
        {
            console.WriteLine("You must specify a subcommand.");
            console.WriteLine();
            app.ShowHelp();
            return 1;
        }
    }
از آنجا که کلاس Program نیز به ویژگی command مزین شده‌است، متد OnExecute را اضافه می‌کنیم. تنها تفاوت این متد با متدهای قبلی، در نوع خروجی آن است که هر مقدار غیر از صفر، به منزله خطا میباشد. در این حالت چون کاربر کامندی را صادر نکرده است، ابتدا به کاربر اجباری بودن کامند را گوشزد کرده و سپس از طریق متد ShowHelp، راهنمای کار با ابزار را به او نشان داده و سپس کد یک را به منزله رخ دادن خطا یا اعلام شرایط غیرعادی بازمیگردانیم. نوع خروجی متد OnExecute در صورتی که void باشد، به معنای مقدار 0 میباشد که در کلاس‌های قبلی از آن استفاده کرده‌ایم.
در نهایت متد Main را نیز به شکل زیر تغییر می‌دهیم:
        static int Main(string[] args)
        {
            return CommandLineApplication.Execute<Program>(args);
        }
تکه کد CommandLineApplication.Execute آرگومان‌های ورودی را دریافت کرده و کامند مورد نظر را شناسایی میکند و همچنین مقدار عددی که از آن جهت return شدن استفاده می‌کند، همان عددهای صفر و غیر صفر میباشد که در بالا توضیح داده شده است.

نمونه استفاده از ابزار نهایی
PS D:\projects\Samples\globaltools> dotnet-notes new-note -t "sample1" -b "this is body"
the note is saved
PS D:\projects\Samples\globaltools> dotnet-notes new-note -t "test1" -b "this is body of another note"
the note is saved
PS D:\projects\Samples\globaltools> dotnet-notes list
sample1
test1
PS D:\projects\Samples\globaltools> dotnet-notes list -g sa
sample1
PS D:\projects\Samples\globaltools> dotnet-notes show -t sample1
this is body
در ابزار بالا کامند new-note به صورت جدا از هم با خط تیره مشخص شده‌است. دلیل این امر نیز جداشدن این کلمات در نام کلاس با حروف بزرگ است. در صورتیکه قصد ندارید نام کامندها با خط تیره از هم جدا شوند، باید نام کلاس را از NewNote به Newnote تغییر دهید.
نظرات مطالب
ASP.NET MVC #4
من قبلا هم این پیغام «خراب بودن» لینک دانلود رو جای دیگر هم دیده بودم.
این‌ها خراب نیستند. روش CodePlex این است که بدون تنظیم Mime type خاصی، یک فایل را به درون مرورگر کاربر flush می‌کند. به این ترتیب کاربر فکر می‌کند که با یک سری اطلاعات باینری خراب شده طرف است که اینطور نیست.
روی لینک کلیک راست کنید و گزینه save as رو انتخاب کنید. به این صورت درست دریافت خواهد شد.
نظرات مطالب
فعال‌سازی استفاده از Session در ASP.NET MVC 4 API Controller ها
بله دوست عزیز ، استفاده از Session مزایا و معایب خودش را به همراه دارد.
اما در یک سیستم فروشگاهی حذف و اضافه شدن کالا در سبد خرید بصورت مکرر انجام میشود و برای اینکه شما چه کاربران مهمان و چه کاربران عضو را مدیریت نموده و بتوانید ترافیک روی بانک اطلاعاتی خود را کاهش دهید میتوانید از Session استفاده نمایید . ( بطور مثال اگر 1000 نفر دریک سایت فروشگاهی که حداقل 100 کالا ارائه شده است را به سبد خرید خود اضافه یا تعداد و ... آنها را ویرایش نمایند در بهترین حال 100000 درخواست به بانک اطلاعاتی ارسال و دریافت خواهد شد)
پرسش‌ها
تا چه میزان کلیدهای خارجی باید در لایه Application بررسی شوند؟

سلام

زمانی که کاربر یک درخواست از نوع POST را به API ارسال میکنه، نتیجه انجام عملیات در متغیری با نام IsSuccess برگردانده میشه. اگر مقدار این متغیر برابر false باشه یعنی متغیر ErrorList حاوی پیغام است.

سناریو:

  • نام Entity در این مثال Product هست که پنج Navigation Property داره که با Entityهای دیگر دارای Relation هستند.
  • لایه Application قبل از اینکه در Entity یک ردیف جدید ثبت کنه ابتدا با دستور Any مقدار یکی از Propertyها را بررسی میکنه و اگر وجود نداشت، یک Error در ErrorList اضافه میکنه و نتیجه را بصورت IsSeccess=false بر میگردونه.
  • در واقع حالا کاربر مطلع هست که مثلا ProductTypeId اشتباه است و اصلا ProductTypeی با این شناسه وجود نداره.

سوال:

  1. آیا ضروریه تا به ازای هر کلید خارجی که در Entity تعریف شده بدین صورت اعتبار تمام آنها بررسی و به کلاینت اعلام شود؟
  2. اگر تعداد کلیدهای خارجی در یک Entity زیاد باشد راه حل چیست؟
  3. آیا اگر اطلاعات را مستقیما به بانک اطلاعاتی ارسال کنیم تا خود بانک اطلاعاتی صحت وجود این کلیدها را بررسی کند بهتر است یا خیر؟
  4. اگر برعهده بانک اطلاعاتی بگذاریم چطور باید به کلاینت و به ازای هر کلید خارجی که باعث بروز Exception شده اطلاع رسانی کنیم؟
  5. در مجموع روش مناسب کدام است؟

تشکر

نظرات مطالب
امن سازی برنامه‌های ASP.NET Core توسط IdentityServer 4x - قسمت ششم - کار با User Claims
این مطلوب است که اطلاعات پویا مانند آدرس یا نقش‌های یک کاربر که پویا هستند را در کلایم‌ها نگهداری کنیم؟ بهترین راه برای بروز بودن همیشگی نقش‌های یک کاربر این است که برای هر درخواست او نقش هارا از IDP دریافت کنیم؟
ضمنا بسته‎ی IdentityModel که معرفی کرده اید با آخرین نسخه نگارش آن در Core 3.1 سازگاری ندارد، آخرین چیزی که بهش رسیدم این بود که درخواست برای  tokenEndpoint ارسال میشود منتهی با خطای unsupported_grant_type مواجه میشوم با GrantType از نوع HybridAndClientCredentials هم تست کردم فرقی نداشته است.