اشتراک‌ها
معرفی C#/WinRT Version 1.0

Today is the official GA release for .NET 5, and along with it we are excited to share the latest updates with our recent release of C#/WinRT version 1.0. C#/WinRT provides WinRT projection support for .NET 5 based apps. The Windows SDK leverages this technology and is now integrated with the .NET 5.0 SDK to expose Windows APIs through the new Target Framework Monikers. In addition to the Windows SDK support added for .NET 5, C#/WinRT itself allows component authors to build their own .NET 5 projections using the CsWinRT NuGet package.  

معرفی C#/WinRT Version 1.0
نظرات مطالب
امن سازی برنامه‌های ASP.NET Core توسط IdentityServer 4x - قسمت پنجم - پیاده سازی ورود و خروج از سیستم
آن بسته برای این است که خودتان UI مدیریتی برای آن طراحی کنید و در این بین پایه‌ای هم در اختیارتان باشد. البته ترکیب بسته‌ی EF آن با بسته‌ی IdentityServer4.AspNetIdentity امکان استفاده‌ی از ASP.NET Core Identity مایکروسافت را به عنوان UI مدیریتی این IDP میسر می‌کند که بررسی آن نیاز به بحثی جداگانه دارد.
مطالب
شروع به کار با Ember.js
Ember.js کتابخانه‌ای است جهت ساده سازی تولید برنامه‌های تک صفحه‌ای وب. برنامه‌هایی که شبیه به برنامه‌های دسکتاپ در مرورگر کاربر عمل می‌کنند. دو برنامه نویس اصلی آن Yehuda Katz که عضو اصلی تیم‌های jQuery و Ruby on Rails است و Tom Dale که ابتدا SproutCore را به وجود آورد و بعدها به Ember.js تغییر نام یافت، هستند.

منابع اصلی Ember.js

پیش از شروع به بحث نیاز است با تعدادی از سایت‌های اصلی مرتبط با Ember.js آشنا شد:
سایت اصلی: http://emberjs.com
مخزن کدهای آن: https://github.com/emberjs
انجمن اختصاصی پرسش و پاسخ: http://discuss.emberjs.com
موتور قالب‌های آن: http://handlebarsjs.com
لیست منابع مطالعاتی مرتبط مانند ویدیوهای آموزشی و لیست مقالات موجود: http://emberwatch.com
و بسته‌ی نیوگت آن: https://www.nuget.org/packages/EmberJS



مفاهیم پایه‌ای Ember.js

شیء Application
 App = Ember.Application.create();
یک برنامه‌ی Ember.js با تعریف وهله‌ای از شیء Application آن آغاز می‌شود. با اینکار به صورت خودکار رویدادگردان‌هایی به صفحه اضافه می‌شوند. کامپوننت‌های پیش فرض آن ایجاد شده و همچنین قالب اصلی برنامه رندر می‌شود.

مسیر یابی
با مرور قسمت‌های مختلف برنامه توسط کاربر، نیاز است حالات برنامه را مدیریت کرد؛ اینجا است که کار قسمت مسیریابی شروع می‌شود. مسیریابی، منابع مورد نیاز جهت آدرس‌های مشخصی را تامین می‌کند.
App.Router.map(function() {
    this.resource('accounts'); // takes us to /accounts
    this.resource('gallery'); // takes us to /gallery
});
در اینجا نحوه‌ی تعریف آغازین مسیریابی Ember.js را مشاهده می‌کنید که توسط متد resource آن مسیرهای قابل ارائه توسط برنامه مشخص می‌شوند.
به این ترتیب مسیرهای accounts/ و gallery/ قابل پردازش خواهند شد.

این مسیرها، تو در تو نیز می‌توانند باشند. برای مثال:
App.Router.map(function() {
    this.resource('news', function() {
        this.resource('images', function () { // takes us to /news/images
            this.route('add');// takes us to /news/images/add
        });
    });
});
به این ترتیب نحوه‌ی تعریف مسیریابی آدرس news/images/add را مشاهده می‌کنید. همچنین در این مثال از دو متد resource و route استفاده شده‌است. از متد resource برای حالت تعریف اسامی استفاده کنید و از متد route برای تعریف افعال و تغییر دهنده‌ها. برای نمونه در اینجا فعل افزودن تصاویر با متد route مشخص شده‌است.


مدل‌ها
مدل‌ها همان اشیایی هستند که برنامه مورد استفاده قرار می‌دهد و می‌توانند یک آرایه‌ی ساده و یا اشیاء JSON دریافتی از وب سرور باشند.
حداقل به دو روش می‌توان مدل‌ها را تعریف کرد:
الف) با استفاده از افزونه‌ی Ember Data
ب) با کمک شیء Ember.Object
App.SiteLink = Ember.Object.extend({});
App.SiteLink.reopenClass({
    findAll: function() {
        var links = [];
        //… $.getJSON …

        return links;
    }
});
ابتدا یک زیرکلاس از Ember.Object به کمک متد extend ایجاد خواهد شد. سپس از متد توکار reopenClass برای توسعه‌ی API کمک خواهیم گرفت.
در ادامه متد دلخواهی را ایجاد کرده و برای مثال آرایه‌ای از اشیاء دلخواه جاوا اسکریپتی را بازگشت خواهیم داد.
پس از تعریف مدل، نیاز است آن‌را به سیستم مسیریابی معرفی کرد:
App.GalleryRoute = Ember.Route.extend({
    model: function() {
        return App.SiteLink.findAll();
    }
});
به این ترتیب زمانیکه کاربر به آدرس gallery/ مراجعه می‌کند، دسترسی به model وجود خواهد داشت. در اینجا model یک واژه‌ی کلیدی است.


کنترلرها
کنترلرها جهت ارائه‌ی اطلاعات مدل‌ها به View و قالب برنامه تعریف می‌شوند. در اینجا همیشه باید بخاطر داشت که model تامین کننده‌ی اطلاعات است. کنترلر جهت در معرض دید قرار دادن این اطلاعات، به View برنامه کاربرد دارد و مدل‌ها هیچ اطلاعی از وجود کنترلرها ندارند.
کنترلرها علاوه بر اطلاعات model، می‌توانند حاوی یک سری خواص و اشیاء صرفا نمایشی که قرار نیست در بانک اطلاعاتی ذخیره شوند نیز باشند.
در Ember.js قالب‌ها (templates) اطلاعات خود را از کنترلر دریافت می‌کنند. کنترلرها اطلاعات مدل را به همراه سایر خواص نمایشی مورد نیاز در اختیار View و قالب‌های برنامه قرار می‌دهند.


برای تعریف یک کنترلر می‌توان درون شیء مسیریابی، با تعریف متد setupController شروع کرد:
App.GalleryRoute = Ember.Route.extend({
    setupController: function(controller) {
        controller.set('content', ['red', 'yellow', 'blue']);
    }
});
در این مثال یک خاصیت دلخواه به نام content تعریف و سپس آرایه‌ای به آن انتساب داده شده‌است.

روش دوم تعریف کنترلرها با ایجاد یک زیر کلاس از شیء Ember.Controller انجام می‌شود:
App.GalleryController = Ember.Controller.extend({
    search: '',
    content: ['red', 'yellow', 'blue'],
    query: function() {
        var data = this.get('search');
        this.transitionToRoute('search', { query: data });
    }
});


قالب‌ها یا templates
قالب‌ها قسمت‌های اصلی رابط کاربری را تشکیل خواهند داد. در اینجا از کتابخانه‌ای به نام handlebars برای تهیه قالب‌های سمت کاربر کمک گرفته می‌شود.
<script type="text/x-handlebars" data-template-name="sayhello">
    Hello,
    <strong>{{firstName}} {{lastName}}</strong>!
</script>
این قالب‌ها توسط تگ اسکریپت تعریف شده و نوع آن‌ها text/x-handlebars مشخص می‌شود. به این ترتیب Ember.js، این قسمت از صفحه را یافته و عبارات داخل {{}} را با مقادیر دریافتی از کنترلر جایگزین می‌کند.
<script type="text/x-handlebars" data-template-name="sayhello">
    Hello,
    <strong>{{firstName}} {{lastName}}</strong>!
 
    {{#if person}}
    Welcome back,
    <strong>{{person.firstName}} {{person.lastName}}</strong>!
    {{/if}}
 
    <ul>
        {{#each friend in friends}}
        <li>
            {{friend.name}}
        </li>
        {{/each}}
    </ul>
 
    <img {{bindAttr src="link.url" }} />
    {{#linkTo ''about}}About{{/linkTo}}
</script>
در این مثال نحوه‌ی تعریف عبارات شرطی و یا یک حلقه را نیز مشاهده می‌کنید. همچنین امکان اتصال به ویژگی‌هایی مانند src یک تصویر و یا ایجاد لینک‌ها را نیز دارا است.
بهترین مرجع آشنایی با ریز جزئیات کتابخانه‌ی handlebars، مراجعه به سایت اصلی آن است.


قواعد پیش فرض نامگذاری در Ember.js
اگر به مثال‌های فوق دقت کرده باشید، خواصی مانند GalleryController و یا GalleryRoute به شیء App اضافه شده‌اند. این نوع نامگذاری‌ها در ember.js بر اساس روش convention over configuration کار می‌کنند. برای نمونه اگر مسیریابی خاصی را به نحو ذیل تعریف کردید:
 this.resource('employees');
شیء مسیریابی آن App.EmployeesRoute
کنترلر آن App.EmployeesController
مدل آن App.Employee
View آن App.EmployeesView
و قالب آن employees
بهتر است تعریف شوند. به عبارتی اگر اینگونه تعریف شوند، به صورت خودکار توسط Ember.js یافت شده و هر کدام با مسئولیت‌های خاص مرتبط با آن‌ها پردازش می‌شوند و همچنین ارتباطات بین آن‌ها به صورت خودکار برقرار خواهد شد. به این ترتیب برنامه نظم بهتری خواهد یافت. با یک نگاه می‌توان قسمت‌های مختلف را تشخیص داد و همچنین کدنویسی پردازش و اتصال قسمت‌های مختلف برنامه نیز به شدت کاهش می‌یابد.


تهیه‌ی اولین برنامه‌ی Ember.js
تا اینجا نگاهی مقدماتی داشتیم به اجزای تشکیل دهنده‌ی هسته‌ی Ember.js. در ادامه مثال ساده‌ای را جهت نمایش ساختار ابتدایی یک برنامه‌ی Ember.js، بررسی خواهیم کرد.
بسته‌ی Ember.js را همانطور که در قسمت منابع اصلی آن در ابتدای بحث عنوان شد، می‌توانید از سایت و یا مخزن کد آن دریافت کنید و یا اگر از VS.NET استفاده می‌کنید، تنها کافی است دستور ذیل را صادر نمائید:
 PM> Install-Package EmberJS
پس از اضافه شدن فایل‌های js آن به پوشه‌ی Scripts برنامه، در همان پوشه‌، فایل جدید Scripts\app.js را نیز اضافه کنید. از آن برای افزودن تعاریف کدهای Ember.js استفاده خواهیم کرد.
در این حالت ترتیب تعریف اسکریپت‌های مورد نیاز صفحه به صورت ذیل خواهند بود:
<script src="Scripts/jquery-2.1.1.js" type="text/javascript"></script>
<script src="Scripts/handlebars.js" type="text/javascript"></script>
<script src="Scripts/ember.js" type="text/javascript"></script>
<script src="Scripts/app.js" type="text/javascript"></script>
کدهای ابتدایی فایل app.js جهت وهله سازی شیء Application و سپس تعریف مسیریابی صفحه‌ی index بر اساس روش convention over configuration به همراه تعریف یک کنترلر و افزودن متغیری به نام content به آن که با یک آرایه مقدار دهی شده‌است:
App = Ember.Application.create();
App.IndexRoute = Ember.Route.extend({
    setupController:function(controller) {
        controller.set('content', ['red', 'yellow', 'blue']);
    }
});
باید دقت داشت که تعریف مقدماتی Ember.Application.create به همراه یک سری تنظیمات پیش فرض نیز هست. برای مثال مسیریابی index به صورت خودکار به نحو ذیل توسط آن تعریف خواهد شد و نیازی به تعریف مجدد آن نیست:
App.Router.map(function() {
    this.resource('application'); 
    this.resource('index');
});
سپس برای اتصال این کنترلر به یک template خواهیم داشت:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script src="Scripts/jquery-2.1.1.js" type="text/javascript"></script>
    <script src="Scripts/handlebars.js" type="text/javascript"></script>
    <script src="Scripts/ember.js" type="text/javascript"></script>
    <script src="Scripts/app.js" type="text/javascript"></script>
</head>
<body>
    <script type="text/x-handlebars" data-template-name="index">
        Hello,
        <strong>Welcome to Ember.js</strong>!
        <ul>
            {{#each item in content}}
            <li>
                {{item}}
            </li>
            {{/each}}
        </ul>
    </script>
</body>
</html>
توسط اسکریپتی از نوع text/x-handlebars، اطلاعات آرایه content دریافت و در طی یک حلقه در صفحه نمایش داده خواهد شد.
مقدار data-template-name در اینجا مهم است. اگر آن‌را به هر نام دیگری بجز index تنظیم کنید، منبع دریافت اطلاعات آن مشخص نخواهد بود. نام index در اینجا به معنای اتصال این قالب به اطلاعات ارائه شده توسط کنترلر index است.

تا همینجا اگر برنامه را اجرا کنید، به خوبی کار خواهد کرد. نکته‌ی دیگری که در مورد قالب‌های Ember.js قابل توجه هستند، قالب پیش فرض application است. با تعریف Ember.Application.create یک چنین قالبی نیز به ابتدای هر صفحه به صورت خودکار اضافه خواهد شد:
<body>
    <script type="text/x-handlebars" data-template-name="application">
        <h1>Header</h1>
        {{outlet}}
    </script>
outlet واژه‌‌ای است کلیدی که سبب رندر سایر قالب‌های تعریف شده در صفحه می‌گردد. مقدار data-template-name آن نیز به application تنظیم شده‌است (اگر این مقدار ذکر نگردد نیز به صورت خودکار از application استفاده می‌شود). برای مثال اگر بخواهید به تمام قالب‌های رندر شده در صفحات مختلف، مقدار ثابتی را اضافه کنید (مانند هدر یا منو)، می‌توان قالب application را به صورت دستی به نحو فوق اضافه کرد و آن‌را سفارشی سازی نمود.



کدهای کامل این قسمت را از اینجا می‌توانید دریافت کنید:
EmberJS01.zip
مطالب
پنج دلیل برای توسعه‌ی وب با ASP.NET Core

یک:  ASP.NET Core مستقل از Platform است

آینده‌ی محتوم نرم‌افزار، توسعه به شیوه‌های مستقل از Platform است. شاید این دلیل به تنهایی برای مهاجرت به ASP.NET Core کافی باشد. امروزه نرم‌افزارهایی که مبتنی بر یک Platform خاص نیستند، نسبت به سایر نرم‌افزارها مزیت رقابتی‌تری دارند. نرم‌افزارهای Cross Platform یا مستقل از Platform، بر روی هر سیستم عاملی اجرا می‌شوند. برای اجرای آنها در کامپیوترهای شخصی یا Server کافیست معماری پردازنده‌ی مرکزی x86 باشد و سیستم عامل نیز یکی از انواع ویندوز، لینوکس یا مک.
دلیل مستقل بودن ASP.NET Core از Platform، مبتنی بودن آن بر NET Core. است. این نسخه از دات‌نت را می‌توان برای سیستم‌‌عامل‌های مختلف از http://dot.net دانلود و نصب کرد.
برای اجرای نرم‌افزارهایی که مبتنی بر NET Core. هستند نیاز به بازنویسی کدها یا استفاده از زبان‌های برنامه‌نویسی جداگانه‌ای نیست. این خاصیت همچنین برای libraryهای استانداردی که از این نسخه از دات‌نت استفاده می‌کنند نیز صادق است.

دو:  Open Source است

یکی از انتقادهایی که سال‌ها به مایکروسافت می‌شد، ناشناخته بودن سورس نرم‌افزارهای این شرکت و انحصار طلبی‌هایش بود. اما در سال‌های اخیر مایکروسافت نشان داده‌است که این جنبه از کاراکترش را به تدریج اصلاح کرده‌است. به طوری که اسکات هانسلمن، یکی از کارمندان این شرکت و وبلاگ‌نویس مشهور در این مورد گفته است:
دلیل آمدن من به مایکروسافت این بود که می‌خواستیم هر چقدر می‌توانیم کارها را Open Source کنیم و یک جامعه‌ی کاربری برای دات‌نت و اوپن سورس بسازیم و حالا به NET Core 1.0. رسیده‌ایم.
زمانی شایعه‌ی لو رفتن بخشی از سورس کد ویندوز ۹۵، در صدر اخبار تکنولوژی بود و این یک شکست برای مایکروسافت محسوب می‌شد. اما امروزه ASP.NET Core با لایسنس MIT عرضه شده است که یکی از آزادترین مجوزهای اوپن سورس است. نرم‌افزارهایی که با این مجوز عرضه می‌شوند، آزادی تغییر کد، ادغام با مجوزهای دیگر، عرضه به عنوان محصول دیگر، استفاده تجاری و ... را به همه‌ی توسعه‌دهندگان می‌دهد.

سه: جدا بودن از Web Server

این نسخه‌ی از APS.NET، کاملاً از وب‌سرور که نرم‌افزارها را هاست می‌کند، جدا (decouple) شده است. اگرچه همچنان استفاده از IIS بر روی ویندوز منطقی به نظر می‌رسد اما مایکروسافت یک پروژه‌ی اوپن سورس دیگری را به نام Kestrel نیز منتشر کرده است.
وب‌سرور Kestrel مبتنی بر پروژه libuv است و libuv در اصل برای هاست کردن Node.js تولید شده بود و تأکید آن بر روی انجام عملیات I/O به صورت asynchronous است.
نکته جالب این است که یک برنامه‌ی مبتنی بر ASP.NET Core، در واقع یک Console Application است که در متد Main آن وب‌سرور فراخوانی می‌شود:
using System;
using Microsoft.AspNetCore.Hosting;
namespace aspnetcoreapp
{
public class Program
{
  public static void Main(string[] args)
  {
   var host = new WebHostBuilder()
                  .UseKestrel()
                  .UseStartup<Startup>()
                  .Build();
   host.Run();
  }
}
}

چهار: تزریق وابستگی (Dependency Injection) تو کار

تزریق وابستگی‌ها برای ایجاد وابستگی سست (loosely coupling) بین اشیاء مرتبط و وابسته به یکدیگر است. به جای نمونه‌سازی مستقیم اشیاء مرتبط، یا استفاده از ارجاع‌های ایستا به آن اشیاء، زمانی که یک کلاس به آنها احتیاج داشته باشد، با روش‌های خاصی از طریق DI به اشیاء مورد نیاز دسترسی پیدا می‌کند. در این استراتژی، ماژول‌های سطح بالا نباید به ماژول‌های سطح پایین وابسته باشند، بلکه هر دو باید به abstraction (معمولا Interface ها) وابسته باشند.
وقتی یک سیستم برای استفاده‌ی از DI طراحی شده‌است و کلاس‌های زیادی دارد که وابستگی‌هایش را از طریق constructor یا property‌ها درخواست می‌کند، بهتر است یک کلاس مخصوص ایجاد آن کلاس‌ها و وابستگی‌هایشان داشته باشد. به این کلاس‌ها container، یا Inversion of Control (IoC) container یا Dependency Injection (DI) container گفته می‌شود.
با این روش، بدون نیاز به hard code کردن instance سازی از کلاس‌ها، می‌توان گراف‌های پیچیده وابستگی را در اختیار یک کلاس قرار داد.
طراحی ASP.NET Core از پایه طوری است که حداکثر استفاده را از Dependency Injection می‌کند. یک container ساده توکار با نام IServiceProvider وجود دارد که به صورت پیش‌فرض constructor injection را پشتیبانی می‌کند.
در ASP.NET Core با مفهومی به نام service سر و کار خواهید داشت که در واقع به type هایی گفته می‌شود که از طریق DI در اختیار شما قرار می‌گیرند. سرویس‌ها در متد ConfigureServices کلاس Startup برنامه شما تعریف می‌شوند. این service‌ها می‌توانند Entity Framework Core یا ASP.NET Core MVC باشند یا سرویس‌هایی که توسط شما تعریف شده‌اند. مثال:
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices (IServiceCollection services)
{
// Add framework services.
services.AddDbContext<ApplicationDbContext>(options =>
  options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<ApplicationUser, IdentityRole>()
  .AddEntityFrameworkStores<ApplicationDbContext>()
  .AddDefaultTokenProviders();
services.AddMvc();
// Add application services.
services.AddTransient<IEmailSender, AuthMessageSender>();
services.AddTransient<ISmsSender, AuthMessageSender>();
}


پنج: یکپارچگی با framework‌های مدرن سمت کلاینت

فرآیند build در برنامه‌های تحت وب مدرن معمولاً این وظایف را انجام می‌دهد:
  • bundle و minify کردن فایل‌های جاوا اسکریپت و همینطور CSS
  • اجرای ابزارهایی برای bundle و minify کردن قبل از هر build
  • کامپایل کردن فایل‌های LESS و SASS در CSS
  • کامپیال کردن فایل‌های CoffeeScript و TypeScript در JavaScript
برای اجرای چنین فرآیندهایی از ابزاری به نام task runner استفاده می‌شود که Visual Studio از دو ابزار task runner مبتنی برا جاوا اسکریپت به نام‌های Gulp و Grunt بهره می‌برد. از این ابزارها با استفاده از ASP.NET Core Web Application template می‌توان در ASP.NET Core استفاده کرد.
همچنین امکان استفاده از Bower که یک package manager (مانند NuGet) برای وب است، وجود دارد. معمولاً از Bower برای نصب فایل‌های CSS ، فونت‌ها، framework‌های سمت کلاینت و کتابخانه‌های جاوا اسکریپت استفاده می‌شود. اگرچه بسیاری از package‌ها در NuGet هم وجود دارند، اما تمرکز بیشتر NuGet بر روی کتابخانه‌های دات‌نتی است.
نصب و استفاده‌ی سایر library‌های سمت کلاینت مانند Bootstrap ، Knockout.js ، Angular JS  و زبان TypeScript نیز در Visual Studio و هماهنگی آن با ASP.NET Core نیز بسیار ساده است.
پس همین حالا دست به کار شوید و با نصب -حداقل - Microsoft Visual Studio 2015 Update 3 بر روی ویندوز یا Visual Studio Code  بر روی هر سیستم عاملی از برنامه‌نویسی با ASP.NET Core لذت ببرید!
منابع :
مطالب
یک سرویس (میکروسرویس) چیست؟ و چگونه آن را مستند کنیم؟ (قسمت دوم)
در قسمت اول این مقاله ، مشخصات کلیدی یک سرویس مورد بررسی قرار گرفت و  API‌ها و وابستگی‌ها یا Dependencies هر سرویس نیز مورد بررسی قرار گرفتند. همانطور که مشخص است با زیاد شدن این سرویس‌ها و وابستگی هایی که به یکدیگر پیدا میکنند، سردرگمی‌ها نیز برای اعضای تیم‌های مختلف، زیاد میگردد. چرا که افراد هر تیم دائما باید از API‌های ارائه شده توسط تیم‌های دیگر مطلع باشند. به همین جهت زمانیکه شما یک سبک معماری مانند میکروسرویس را انتخاب می‌نمایید، باید یک روش مستند سازی مناسب را نیز انتخاب نمایید تا مانع از پیچیدگی و سردرگمی ناشی از نبود مستندات مناسب و سربار هماهنگی بین تیمی شوید.

در این مطلب، 2 روش زیر، جهت مستند سازی سرویس‌ها بررسی می‌شوند:
 روش اول - کارت طراحی میکروسرویس (microservice design card)
 روش دوم - بوم میکروسرویس ( microservice canvas)

لازم به ذکر است که دو روش فوق می‌توانند مکمل یکدیگر باشند؛ همچنین این اسناد (علاوه بر مفید بودن برای مصرف کنندگان سرویس) حتی جهت شناسایی سرویس‌ها و ارتباطات بین آنها در زمان تحلیل (در جلساتی مانند event storming) نیز می‌توانند کاربردی باشند.


روش اول - کارت طراحی میکروسرویس (microservice design card) 
روش کارت طراحی میکروسرویس بر اساس کارت‌های CRC که گاهی اوقات در Object-oriented design استفاده می‌شوند، مدل سازی شده‌است و می‌توان از آن جهت ثبت خدمات سرویس و همچنین تعاملات سرویس، با سایر سرویس ها، استفاده نمود (این اطلاعات نسبت به اطلاعات قابل درج در microservice canvas که در ادامه بررسی می‌شود، کمتر است).
می‌توانید این کارت‌ها را در ابعاد کوچک و به تعداد کافی پرینت و در هنگام تحلیل و طراحی سرویس(ها)، از آنها استفاده نمایید
در نهایت جهت کشیدن نقشه وابستگی سرویس‌ها، کارت‌ها روی یک برد نصب و با کشیدن خطوط بین سرویس‌ها، وابستگی‌های هر یک را مشخص نمایید. مزیت اصلی این روش در طراحی، همکاری بیشتر تیم‌ها با یکدیگر می‌باشد.

(نمونه ای از کارت طراحی ‌های مربوط سرویس‌های project و archive)



روش دوم  - بوم میکروسرویس (microservice canvas)
یکی دیگر از روش‌های مناسب برای مستند سازی یک سرویس و ساختار درونی آن، استفاده از روش بوم میکروسرویس می‌باشد. بوم میکروسرویس نیز تا حدودی شبیه به کارت‌های CRC و همچنین روش microservice design card که پیش‌تر بررسی گردید، می‌باشد؛ با این تفاوت که اطلاعات بیشتری را نگهداری می‌نماید.
روش طراحی روی بوم جهت مستند سازی، از گذشته در صنایع مختلفی از جمله صنعت نرم افزار رایج بوده است؛ ولی ظاهرا برای اولین بار در سال 2017 و در این مقاله  (از سایت DZone که توسط Matt McLarty و Irakli Nadareishvili منتشر شده‌است) از این روش به عنوان روشی برای مستند سازی سرویس‌ها (در معماری میکروسرویس) استفاده شده‌است . پس از آن و در طول زمان، نمونه‌های مختلف و نسبتا مشابهی از این بوم توسط افراد و شرکت‌های مختلف ارائه شد (که با جستجوی عبارت microservice canvas در بخش تصاویر سایت گوگل می‌توانید نمونه‌های متفاوت آن را بررسی نمایید). در ادامه این مقاله، بوم میکروسرویسی که آقای ریچاردسون در سال 2019 معرفی نمودند، بررسی می‌گردد.

تصویر فوق بوم مربوط به سرویس Order می‌باشد

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

نمای بیرونی یک سرویس (A service’s external view) در بوم میکروسرویس توسط بخش‌های زیر معرفی می‌گردد
• Name – نام سرویس
• Description – ارائه یک توضیح مختصر در مورد سرویس
• Capabilities – معرفی بخش‌هایی از منطق کسب و کار که در این سرویس پیاده سازی شده‌است.
• Service APIs – معرفی عملیات یا operations (شامل commands  و queries) که در این سرویس پیاده سازی شده‌اند و همچنین معرفی وقایع یا همان domain event هایی که توسط سرویس منتشر می‌شوند.
• Quality attributes – معرفی non-functional requirements‌های سرویس
• Observability (قابلیت‌های مشاهده و بررسی  سرویس) – معرفی health check endpoints و key metrics و ... .

وابستگی‌های یک سرویس (A service’s dependencies)  که لزوما استفاده بیرونی ندارد و بیشتر منبعی برای خود اعضای تیم خواهد بود، در بخشی تحت عنوان dependencies مشخص می‌شوند که خود شامل دو قسمت به شرح زیر می‌باشد: 
• Invokes – عملیاتی که در سایر سرویس‌ها پیاده سازی شده‌اند و در این سرویس فراخوانی می‌گردند.
• Subscribes – اشتراک در کانال پیام‌هایی که شامل وقایع سایر سرویس‌ها می‌باشند.

موارد مربوط به پیاده سازی یک سرویس (A service’s implementation)
در بوم میکروسرویس علاوه بر تمام موارد فوق، شما میتوانید مدل پیاده سازی لایه دامنه را نیز معرفی نمایید. همچنین نام bounded context‌ها و aggregateهای پیاده سازی شده در این سرویس، در این بخش نوشته می‌شود (که در یک حالت ایده آل، تنها یک agg از یک bc در یک سرویس پیاده سازی خواهد شد).

تولید بوم میکروسرویس 
با توجه به دغدغه ناشی از به روز نگه داشتن بوم میکروسرویس (و به طور کلی مستندات پروژه) همراه با تغییرات پروژه، تکنیک‌ها و ابزارهایی جهت تولید خودکار فایل json بوم میکروسرویس (microservice-canvas-tools) و همچنین جهت به تصویر کشیدن فایل json تولید شده (microservices-design-canvas-editor ) وجود دارد. اما اگر ابزار مناسبی را با توجه به پلتفرم مورد نظر، نتواستید پیدا کنید و یا فرصت توسعه یک ابزار اختصاصی نبود، همواره می‌توان این فایل را به صورت دستی نیز ایجاد نمود و در مخزن کد مربوط به پروژه و در کنار سورس اصلی نگه داری کرد تا همراه با سایر مستندات پروژه، این سند نیز پس از هر تغییر به روز شود. نسخه‌ای از آن را نیز می‌توان در محلی مناسب با سایر تیم‌ها به اشتراک گذاشت.

در صورتیکه قصد تولید و توسعه دستی این سند را دارید، نسخه‌ای از آن را در قالب فایل ورد، می‌توانید در این مخزن در گیت هاب پیدا نمایید.
مطالب
پیاده سازی عملیات CRUD با استفاده از پروتکل OData
OData  یکی از بهترین روش‌های پیاده سازی RESTful Apis میباشد. Open Data Protocol یا به اصطلاح OData یک data access protocol برای وب میباشد که اجازه‌ی تغییر دادن و نوشتن کوئری درون CRUD مربوطه را میدهد (create - read - update - delete). Asp.Net WebApi از ورژن 3 و 4 این پروتکل بطور کامل پشتیبانی می‌نماید.
در این آموزش ما از WebApi 2.2 , OData V4, Ef 6 استفاده کرده‌ایم.
با استفاده از ویژوال استودیو یک پروژه‌ی Asp.Net را از نوع Empty به نام ProductService میسازیم.

هم چنین در قسمت Add folders and core references تیک گزینه‌ی Web Api را نیز فعال مینماییم.


حال احتیاج به نصب پکیج OData با استفاده از nuget package manager داریم. کافیست دستور زیر را در package manager console وارد نماییم.

Install-Package Microsoft.AspNet.Odata

این دستور آخرین ورژن Odata package را از nuget دانلود مینماید.

بعد از نصب شدن OData نیاز به اضافه کردن یک Model داریم. کلاسی را به نام Product در پوشه‌ی Models میسازیم.

کلاس Product.cs حاوی فیلد‌های زیر است.

namespace ProductService.Models
{
    public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public decimal Price { get; set; }
        public string Category { get; set; }
    }
}

پراپرتی Id، کلید این entity است و کلاینت میتواند کوئری را بر روی entity، به وسیله‌ی key بزند. برای مثال برای گرفتن Product با Id برابر 2، باید این url را ارسال نمود "(2)Products/"

پرواضح است که Id در Database به عنوان Primary key در نظر گرفته شده است.

حال احتیاج به نصب Entity Framework داریم که با ارسال دستور زیر از طریق nuget نصب خواهد شد

Install-Package EntityFramework

بعد از نصب کردن ef نیاز به اضافه کردن connection string در web config داریم.

<connectionStrings>
    <add name="ProductsContext" connectionString="Data Source=.; 
        Initial Catalog=ProductsContext; Integrated Security=True;MultipleActiveResultSets=True;"
      providerName="System.Data.SqlClient" />
  </connectionStrings>

الان میتوانیم کلاس ProductsContext را درون پوشه‌ی Models ایجاد نماییم. محتویات آن را به صورت زیر وارد مینماییم

using System.Data.Entity;
namespace ProductService.Models
{
    public class ProductsContext : DbContext
    {
        public ProductsContext() 
                : base("name=ProductsContext")
        {
        }
        public DbSet<Product> Products { get; set; }
    }
}

درون Constructor کلاس ProductsContext، داریم name=ProductsContext که باید برابر name درون connection string باشد.

حال نیاز به کانفیگ OData داریم. درون پوشه‌ی App_Start و کلاس WebApiConfig.cs محتویات زیر را جایگزین متد register نمایید:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        ODataModelBuilder builder = new ODataConventionModelBuilder();
        builder.EntitySet<Product>("Products");
        config.MapODataServiceRoute(
            routeName: "ODataRoute",
            routePrefix: null,
            model: builder.GetEdmModel());
    }
}

این کد دو فرآیند زیر را انجام میدهد

1) ساخت Entity Data Model (EDM)

2) اضافه کردن route

EDM یک مدل انتزاعی از data است. EDM برای تولید سند metadata استفاده میشود. کلاس ODataModelBuilder برای ساخت EDM با استفاده از default naming convention میباشد که باعث کاهش کد‌ها میشود. ضمنا کلاس MapODataServiceRoute برای ساخت OData v4 route میباشد. همانگونه که اطلاع دارید، تعریف route برای مدیریت کردن WebApi و چگونگی مسیریابی درخواست‌های http میباشد.

اگر application شما احتیاج به چند OData endpoint داشته باشد، میتوانید برای هر کدام route‌های جدا و همچنین نام یکتایی را برای routeName و routePrefix آن در نظر بگیرید.


اضافه کردن OData Controller

یک Controller، کلاسی برای مدیریت کردن درخواست‌های http میباشد. شما باید Controllerهای مجزایی را برای هر entity set در OData service خود بسازید. در این مقاله Controller مربوط به موجودیت Product را میسازیم.

در Solution Explorer با کلیک راست بر روی پوشه‌ی Controller، کلاسی به نام ProducsController را میسازیم. دقت کنید نام آن حتما باید به Controller ختم شود.

در OData V3 میتوانیم Controller را با استفاده از Scaffolding بسازیم؛ ولی در V4 این ویژگی وجود ندارد!

محتویات زیر را در این کنترلر اضافه مینماییم:

using ProductService.Models;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.OData;
namespace ProductService.Controllers
{
    public class ProductsController : ODataController
    {
        ProductsContext db = new ProductsContext();
        private bool ProductExists(int key)
        {
            return db.Products.Any(p => p.Id == key);
        } 
        protected override void Dispose(bool disposing)
        {
            db.Dispose();
            base.Dispose(disposing);
        }
    }
}

این مرحله‌ی ابتدایی از پیاده سازی کنترلر میباشد و در قسمت بعد به پیاده سازی CRUD مربوط به آن میپردازیم.


Querying The Entity Set

این 2 متد را به کنترلر خود اضافه مینماییم

[EnableQuery]
public IQueryable<Product> Get()
{
    return db.Products;
}
[EnableQuery]
public SingleResult<Product> Get([FromODataUri] int key)
{
    IQueryable<Product> result = db.Products.Where(p => p.Id == key);
    return SingleResult.Create(result);
}

ویژگی EnableQuery به معنای امکان Query زدن از سمت کلاینت به آن میباشد. FromODataUri نیز برای امکان پاس دادن پارامتر از طریق Uri است.

متد Get بدون پارامتر، قادر به برگرداندن تمامی Product‌ها میباشد و متد Get با پارامتر، قادر به برگرداندن آن Product خاص با استفاده از unique Id است.

در صورت داشتن EnableQuery با استفاده از Query Option هایی مثل filter$ و sort$ و غیره از سمت کلاینت قادر به تغییر دادن کوئری‌های خود هستیم.


Adding and Entity to Entity Set

برای اجازه دادن به کلاینت، جهت اضافه کردن یک Product به دیتابیس، متد Post زیر را اضافه مینماییم

public async Task<IHttpActionResult> Post(Product product)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }
    db.Products.Add(product);
    await db.SaveChangesAsync();
    return Created(product);
}


Updation an Entity

OData از دو روش متفاوت برای Update کردن یک موجودیت استفاده مینماید.

1) Patch : امکان partial update برای موجودیت مربوطه را فراهم میسازد.

2) Put : موجودیت جدید را به صورت کامل جایگزین مینماید.

مشکل روش Put این است که کلاینت مجبور به ارسال تمامی فیلد‌های مربوطه میباشد. حتی آن هایی که اساسا تغییری نکرده‌اند. بنابراین روش Patch ترجیح داده میشود.

در هر صورت ما به پیاده سازی هر دو روش می‌پردازیم:

public async Task<IHttpActionResult> Patch([FromODataUri] int key, Delta<Product> product)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }
    var entity = await db.Products.FindAsync(key);
    if (entity == null)
    {
        return NotFound();
    }
    product.Patch(entity);
    try
    {
        await db.SaveChangesAsync();
    }
    catch (DbUpdateConcurrencyException)
    {
        if (!ProductExists(key))
        {
            return NotFound();
        }
        else
        {
            throw;
        }
    }
    return Updated(entity);
}
public async Task<IHttpActionResult> Put([FromODataUri] int key, Product update)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }
    if (key != update.Id)
    {
        return BadRequest();
    }
    db.Entry(update).State = EntityState.Modified;
    try
    {
        await db.SaveChangesAsync();
    }
    catch (DbUpdateConcurrencyException)
    {
        if (!ProductExists(key))
        {
            return NotFound();
        }
        else
        {
            throw;
        }
    }
    return Updated(update);
}

در قسمت Patch کنترلر از <Delta<T استفاده میکند که typeی است برای track کردن تغییرات در مدل مربوطه.


Deleting an Entity

برای حذف هر موجودیت نیز کافیست متد زیر را به کنترلر خود اضافه نمایید:

public async Task<IHttpActionResult> Delete([FromODataUri] int key)
{
    var product = await db.Products.FindAsync(key);
    if (product == null)
    {
        return NotFound();
    }
    db.Products.Remove(product);
    await db.SaveChangesAsync();
    return StatusCode(HttpStatusCode.NoContent);
}

من چند رکورد تستی را به صورت زیر وارد کرده‌ام:

حال پروژه‌ی خود را run نموده و آدرس زیر را وارد نمایید:

http://localhost:YourPort/Products

پاسخ، مجموعه‌ای از entity‌های زیر خواهد بود:

{
  "@odata.context":"http://localhost:4516/$metadata#Products","value":[
    {
      "Id":1,"Name":"Ali","Price":2.00,"Category":"aaa"
    },{
      "Id":2,"Name":"Reza","Price":1.00,"Category":"bbb"
    },{
      "Id":3,"Name":"Ahmad","Price":0.00,"Category":"ccc"
    }
  ]
}

شما میتوانید از هر کدام از فیلتر‌های زیر برای کوئری زدن از کلاینت به سمت سرور استفاده نمایید. بطور مثال هر کدام از اینها پاسخ متفاوت و مربوط به خود را برگشت میدهد:

/Products(2)

Productی با آی دی 2 را بر میگرداند.

/Products?$filter=Id gt 1

محصولی را با آی دی بزرگتر از 1، بر میگرداند.

Products?$select=Name

روی محصولات select زده و فقط فیلد Name آن‌ها را بر میگرداند.

Products?$select=Name,Price

آرایه‌ای از objectهایی با پراپرتی Name و Price را بر میگرداند.

/Products?$top=3

فقط 3 رکورد اول را بر میگرداند.


همانطور که ملاحظه میفرمایید، استفاده از OData باعث کمتر شدن کد‌های سمت سرور و همچنین امکان کوئری زدن از سمت کلاینت به سمت سرور را مهیا می‌کند.

بعد از خواندن این مقاله ممکن است به این مساله فکر کنید که این کار باعث کاهش امنیت میشود. باید عرض کنم که امکانات زیادی برای محدود کردن کوئری‌ها، فراهم شده است و هیچ نگرانی از این بابت وجود ندارد. بطور مثال میتوانید تعیین کنید که از entity مربوطه فقط حداکثر 3 پراپرتی قابلیت کوئری زدن را دارند؛ یا اینکه حداکثر در هر کوئری، 10 رکورد قابلیت پاسخ دادن خواهد داشت.

پس بدین صورت میباشد که شما حداکثر امکانات ممکن را به سمت کلاینت میدهید و اختیار بدان واگذار شده که آیا از این امکانات حداکثری، استفاده نماید یا خیر.

امکانات این پروتکل منحصر به فرد است و در مقاله‌های بعدی به جزئیات بیشتر و دقیق‌تری خواهیم پرداخت.

مطالب
آشنایی با NuGet - قسمت دوم

قسمت قبل از دید یک مصرف کننده بود؛ این قسمت جهت توسعه‌ دهنده‌ها تهیه شده است. کسانی که قصد دارند تا بسته‌های NuGet ایی از کارشان تهیه کنند. مراحل اینکار به شرح زیر است:

الف) برای این منظور نیاز است تا برنامه‌ی‌ خط فرمان NuGet.exe معرفی شده در قسمت قبل را ابتدا دریافت کنید : (+)

ب) برای بسته نرم افزاری خود یک پوشه جدید درست کنید. سپس فرمان nuget.exe spec را در این پوشه صادر نمائید. بلافاصله فایلی به نام Package.nuspec تشکیل خواهد شد:
D:\Prog\1389\CodePlex\slpdatepicker\SlPDatePickerNuGet>NuGet.exe spec
Created 'Package.nuspec' successfully.

فایل Package.nuspec، یک فایل XML ساده است. آن‌را با یک ادیتور متنی باز کرده و تغییرات لازم را اعمال نمائید. برای مثال من جهت پروژه Silverlight 4 Persian DatePicker ، محتویات آن‌را به صورت زیر تغییر داده‌ام:

<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>Silverlight.4.Persian.DatePicker</id>
<version>1.0</version>
<authors>Vahid Nasiri</authors>
<owners>Vahid Nasiri</owners>
<licenseUrl>http://slpdatepicker.codeplex.com/license</licenseUrl>
<projectUrl>http://slpdatepicker.codeplex.com/</projectUrl>
<iconUrl>https://slpdatepicker.svn.codeplex.com/svn/SilverlightPersianDatePicker/Views/Images/date.png</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Silverlight 4 Persian DatePicker Control</description>
<tags>Silverlight WPF Persian DatePicker</tags>
</metadata>
<files>
<file src="..\SilverlightPersianDatePicker\Bin\Release\*.dll" target="lib" />
<file src="..\SilverlightPersianDatePicker\Bin\Release\*.pdb" target="lib" />
<file src="..\SilverlightPersianDatePicker\Bin\Release\*.xml" target="lib" />
</files>
</package>

همانطور که ملاحظه می‌کنید یک سری اطلاعات عمومی از پروژه مورد نظر درخواست شده است؛ برای مثال آدرس آیکن آن چیست یا کجا می‌توان آن‌را یافت؟ مجوز استفاده از آن چیست و مواردی از این دست. به کمک تگ files هم فایل‌های کتابخانه در اینجا لحاظ شده‌اند. فایل آیکن معرفی شده باید در اندازه‌ی 32*32 و با فرمت png باشد. باید دقت داشت که در سایت nuget.org ، بسته شما بر اساس id ذکر شده معرفی خواهد شد و آدرسی بر این اساس تشکیل می‌گردد. بنابراین از فاصله یا موارد مشکل ساز در این بین استفاده نکنید.

در مورد نحوه‌ی ایجاد قدم به قدم یک پروژه جدید در سایت کدپلکس می‌توان به این مطلب مراجعه نمود: (+)

ج) اکنون نوبت به تهیه بسته نهایی می‌رسد. برای این منظور دستور زیر را در خط فرمان صادر کنید:
NuGet.exe pack Package.nuspec
پس از چند لحظه فایل Silverlight.4.Persian.DatePicker.1.0.nupkg جهت ارائه عمومی تولید خواهد شد.

د) قبل از اینکه این فایل نهایی را در سایت nuget.org آپلود کنیم، می‌توان مشخصات آن‌را به صورت محلی نیز یکبار مرور کرد. برای این منظور در VS.NET به منوی Tools گزینه‌ی Options مراجعه کرده و در قسمت package manager ، آدرس پوشه بسته مورد نظر را وارد کنید. برای مثال:



اکنون اگر کنسول پاورشل توضیح داده شده در قسمت قبل را باز نمائید، منبع جدید اضافه شده مشخص است یا می‌توان توسط دستور ذیل از آن کوئری گرفت:
get-package -remote -filter silverlight



و یا اگر همانند توضیحات قبل به صفحه‌ی دیالوگ add library package reference‌ مراجعه کنیم، مشخصات کامل بسته به همراه منبع محلی باید قابل مشاهده باشند:



ه) پس از بررسی محلی بسته مورد نظر، اکنون نوبت به ارائه عمومی آن می‌باشد. برای این منظور ابتدا باید در سایت nuget.org ثبت نام کرد : (+). اگر آدرس ایمیل شما را نپذیرفت، از مرورگر IE استفاده کنید!
پس از ثبت نام تنها کافی است به قسمت contribute سایت مراجعه کرده و فایل بسته نهایی را در آنجا آپلود کرد. به این صورت بسته نهایی در سایت پدیدار خواهد شد :‌(+)
همچنین بلافاصله در قسمت گالری آنلاین صفحه add library package reference نیز قابل دسترسی خواهد بود.


در آینده جهت توزیع به روز رسانی‌های جدید، همین مراحل باید تکرار شوند. البته در نظر داشته باشید که version ذکر شده در فایل Package.nuspec را باید حتما تغییر داد تا بسته‌ها از یکدیگر متمایز شوند. امکان اتوماسیون این توزیع نیز وجود دارد. همان فایل nuget.exe ، امکان ارسال بسته نهایی را به سایت nuget.org نیز دارد:
nuget push name.nupkg key
در اینجا key مخصوص به خود را می‌توان در صفحه‌ی http://nuget.org/Contribute/MyAccount مشاهده و استفاده نمود.

اگر علاقمند به مشاهده جزئیات بیشتری از این پروسه هستید، می‌توان به سایت رسمی آن مراجعه کرد: (+)

نظرات مطالب
NuGet 2.0 منتشر شد
اگر موقعی که نسخه قدیمی Nuget نصب باشه اقدام به نصب ASP.NET MVC 4 RC کنید با شکست مواجه خواهید شد هیچ راهی هم جز حذف کردن Nuget ندارید.

بسته MVC خودش حاوی Nuget هست  ونمیدونم چرا نمیتونه آپدیتش کنه!
اشتراک‌ها
NetVips 1.0 کتابخانه‌ای برای کار با تصاویر مخصوص Mono/.NET

NetVips is a wrapper for the libvips image processing library. It's a bit like Magick.NET, but typically 8x faster. It's API-stable, supports around 300 image-processing operations, and a good range of image formats is supported.

NuGet package: https://www.nuget.org/packages/NetVips

There's a benchmark here: https://github.com/kleisauke/net-vips/tree/master/tests/NetVips.Benchmarks

Formatted docs, including a tutorial and full API: https://kleisauke.github.io/net-vips/

Blog post: https://jcupitt.github.io/libvips/2018/04/10/libvips-for-dot-net.html

NetVips 1.0 کتابخانه‌ای برای کار با تصاویر مخصوص Mono/.NET