نظرات مطالب
ASP.NET MVC #3
البته اگر به تاریخچه Razor مراجعه کنید (^)، اول در تاریخ June 2010 برای MVC‌ و سپس در سال 2011 برای استفاده در Microsoft WebMatrix نیز درنظر گرفته شد.
مطالب
اجزاء معماری سیستم عامل اندروید (قسمت اول معماری امنیتی اندروید) :: بخش سوم
همانطور که در مطالب قبلی توضیح داده شد، اندروید بر روی هسته‌ی لینوکس نگارش 2.6 به بالا اجرا می‌شود. در این مطلب قصد داریم تا نگاهی به معماری امنیتی اندروید داشته باشیم.
Privilege Separation به چه معناست؟
هسته‌ی اندروید یک مدل جداسازی امتیازی (Privilege separation) را در زمان اجرای برنامه‌های کاربردی اجرا می‌کند. این مورد به این معنا است که مانند سیستم یونیکس، سیستم‌عامل اندروید به یک برنامه نیاز دارد تا تنها با شناسه‌ی کاربر خود و شناسه‌ی گروه خاص خودش اجرا شود. بخش‌های معماری سیستم اندروید به این روش از هم جدا شده‌اند. Privilege Separation یک ویژگی امنیتی مهم است؛ زیرا رایج‌ترین انواع حملات را انکار می‌کند و در نتیجه یکی از اولویت‌های یک برنامه می‌باشد. از آنجایی که عملیات جداسازی امتیازی را هسته انجام می‌دهد، لذا این مورد یکی از مباحث پر اهمیت در طراحی هسته می‌باشد که به شدت مورد توجه خواهد بود. تنها فلسفه پشت این طرح این است که اطمینان حاصل شود، هیچ برنامه‌ی کاربردی نمی‌تواند به کد یا داده‌های دیگر برنامه‌ها و یا به دستگاه کاربر و یا خود سیستم نفوذ کند. یک برنامه ممکن است مستقیما از فهرست تماس دستگاه یا تقویم خوانده نشود! این ویژگی همچنین به عنوان sandboxing شناخته می‌شود.
Permissions چگونه کار می‌کند؟
اجازه دهید با یک مثال ساده توضیح دهم: ما برنامه‌ای را داریم که صدا را ضبط کرده و آن‌را از طریق میکروفن دستگاه پخش می‌کند. برای اینکه برنامه به‌درستی کار کند، توسعه دهنده باید یک درخواست دسترسی به RECORD_AUDIO را برای اجازه دسترسی به ضبط صدا، در فایل AndroidManifest.xml بفرستد. این کار به برنامه ما اجازه می‌دهد تا از مؤلفه‌های سیستم که ضبط صدا را کنترل می‌کنند، استفاده کنیم. یک سؤال اینجا مطرح می‌شود که «چه کسی تصمیم می‌گیرد که این دسترسی داده شود یا اینکه تکذیب شود؟»
فقط و فقط هسته‌ی اندروید به کاربر نهایی اجازه می‌دهد تا این فرآیند تایید نهایی را انجام دهد؛ نه هیچ سیستم دیگر یا کاربر دیگری! زمانیکه کاربر، برنامه ما را نصب می‌کند، این کار او را تشویق می‌کند تا این عملیات را انجام دهد. به این نکته دقت کنید که عجله ای برای این دسترسی وجود ندارد و هر زمانیکه برنامه نصب شد، اتفاق خواهد افتاد و این مجوز دسترسی تنها در زمان نصب به کاربر داده می‌شود نه قبل از آن. (به تصویر زیر دقت کنید)

 اگر ما درخواست خود را برای دسترسی به RECORD_AUDIO ثبت نکنیم یا اگر صاحب دستگاه تائید نکند که پس از درخواست ما اجازه استفاده از آن را بدهد، آنگاه یک استثناء به حافظه‌ی مجازی (VM) داده خواهد شد و برنامه با شکست روبرو می‌شود. این مفهوم برای توسعه دهنده‌است که بداند در خواستی را صادر کرده است یا خیر؟ پس برای درخواست مجوز مورد نظر باید برچسب زیر، در فایل AndroidManifest.xml درج شود.
<uses-permission android:name="android.permission.RECORD_AUDIO" />

Application Code Signing
هر برنامه‌ی کاربردی که بر روی سیستم‌عامل اندروید اجرا می‌شود، باید امضاء شود. اندروید از گواهی توسعه دهندگان فردی برای شناسایی آن‌ها و ایجاد روابط اعتمادسازی استفاده می‌کند که در میان کاربردهای مختلفی که در سیستم‌عامل اجرا می‌شوند پیاده می‌شود. 
سیستم‌عامل مجاز به اجرای برنامه‌ای بدون امضاء نخواهد بود. 
استفاده‌ی از یک مرجع، برای صدور امضای یک برنامه لازم نیست؛ چرا که سیستم امنیتی اندروید تنها از یک امضای تک گانه که توسعه دهنده در برنامه قرار داده‌است پیروی می‌کند! مجوزهای کنترلی برنامه مانند امضاء در طول نصب برنامه از طریق هسته‌ی اندروید بررسی شده و ضمانت و تایید خواهند شد. تمامی این فرآیندها به صورت خودکار و بلادرنگ در پشت پرده به سرعت اتفاق می‌افتند! در این صورت اگر گواهی اعتماد (certificate) توسط توسعه دهنده منقضی شود و یا به نحوی مورد اطمینان برای دستگاه نباشد، تمامی عملیات‌های ذکر شده بر روی برنامه به صورت عادی، ادامه خواهند یافت.
مطالب
چک لیست تهیه یک گزارش خوب

مشخصات یک گزارش خوب عموما به شرح زیر است:

1- باید هر سطر گزارش شماره ردیف داشته باشد. (باید امکان ارجاع به هر سطر در صورت بروز مشکل میسر باشد)
2- باید در هر صفحه، شماره صفحه و تعداد کل صفحات ذکر شود. (اگر چاپ شد بر این اساس بتوان ارتباط بین صفحات را یافت)
3- در هر صفحه باید تاریخ و ساعت روز تهیه گزارش حتما ذکر شود. (بعدا جهت رفع اختلافات لازم می‌شود. مثلا می‌گویند این عدد اشتباه است. اما واقعا این عدد در زمان تهیه گزارش درست بوده، اما الان بر اساس اطلاعات جدید ... بله ... چیزی دیگری است، یا به قول آن‌ها اشتباه است)
4- در پایان هر صفحه، یک سری از ستون‌های عددی باید جمع کل داشته باشد.
5- در ابتدای هر صفحه باید "نقل از صفحه قبل" یا همان سطر جمع کل صفحه قبل ذکر شود.
6- هدر گزارش باید در تمام صفحات تکرار شود. (باید مشخص باشد این صفحه گزارش که الان به دست من رسیده متعلق به کجاست، عنوانش چیست حداقل؟)
7- سر ستون‌ها هم باید در هر صفحه تکرار شوند. (مثلا الان صفحه 20 یک گزارش پیش روی شما است. باید بدانید معنای این ستون سوم ظاهر شده در گزارش چیست)
8- تمام اعداد موجود در گزارش باید جداکننده سه رقمی داشته باشند. (خواندن 4446327531 ساده‌تر است یا خواندن 4,446,327,531 ؟)
9- تمام اعداد گزارش باید فارسی نمایش داده شوند. (این مورد را می‌شود با فونت‌های دستکاری شده که احتمالا شما هم یک دوجین از آن‌ها را دارید، حل کرد. فونت‌هایی که با یک فونت ادیتور مثل برنامه معروف FontCreator ویرایش شده و بجای اعداد انگلیسی آن‌ها، همان اعداد فارسی قرار گرفته‌اند)

مطالب دوره‌ها
گزارش درصد پیشرفت عملیات در اعمال غیرهمزمان
گزارش درصد پیشرفت عملیات در اعمال طولانی، امکان لغو هوشمندانه‌تری را برای کاربر فراهم می‌کند. در دات نت 4.5 دو روش برای گزارش درصد پیشرفت عملیات اعمال غیرهمزمان تدارک دیده شده‌اند:
- اینترفیس جنریک IProgress واقع در فضای نام System
- کلاس جنریک Progress واقع در فضای نام System

در اینجا وهله‌ی از پیاده سازی اینترفیس IProgress به Task ارسال می‌شود. در این بین، عملیات در حال انجام با فراخوانی متد Report آن می‌تواند در هر زمانیکه نیاز باشد، درصد پیشرفت کار را گزارش کند.
namespace System
{
  public interface IProgress<in T>
  {
      void Report( T value );
  }
}
البته برای اینکه کار تعریف و پیاده سازی اینترفیس IProgress اندکی کاهش یابد، کلاس توکار Progress برای اینکار تدارک دیده شده‌است. نکته‌ی مهم آن استفاده از Synchronization Context برای ارائه گزارش پیشرفت در ترد UI است تا به سادگی بتوان از نتایج دریافتی، در رابط کاربری استفاده کرد.
namespace System
{
  public class Progress<T> : IProgress<T>
  {
    public Progress();
    public Progress( Action<T> handler );
    protected virtual void OnReport( T value );
  }
}


یک مثال از گزارش درصد پیشرفت عملیات به همراه پشتیبانی از لغو آن

using System;
using System.Threading;
using System.Threading.Tasks;

namespace Async09
{
    public class TestProgress
    {
        public async Task DoProcessingReportProgress()
        {
            var progress = new Progress<int>(percent =>
            {
                Console.WriteLine(percent + "%");
            });

            var cts = new CancellationTokenSource();

            // call some where cts.Cancel();

            try
            {
                await doProcessing(progress, cts.Token);
            }
            catch (OperationCanceledException ex)
            {
                //todo: handle cancellations
                Console.WriteLine(ex);
            }

            Console.WriteLine("Done!");
        }

        private static async Task doProcessing(IProgress<int> progress, CancellationToken ct)
        {
            await Task.Run(async () =>
            {
                for (var i = 0; i != 100; ++i)
                {
                    await Task.Delay(100, ct);
                    if (progress != null)
                        progress.Report(i);

                    ct.ThrowIfCancellationRequested();
                }
            }, ct);
        }
    }
}
متد private static async Task doProcessing طوری طراحی شده‌است که از مفاهیم لغو یک عملیات غیرهمزمان و همچنین گزارش درصد پیشرفت آن توسط اینترفیس IProgress پشتیبانی می‌کند. در اینجا هر زمانیکه نیاز به گزارش درصد پیشرفت باشد، متد Report وهله‌ی ارسالی به آرگومان progress فراخوانی خواهد شد.
برای تدارک این وهله، از کلاس توکار Progress دات نت در متد public async Task DoProcessingReportProgress استفاده شده‌است.
این متد جنریک بوده و برای مثال نوع آن در اینجا int تعریف شده‌است. سازنده‌ی آن می‌تواند یک callback را قبول کند. هر زمانیکه متد Report در متد doProcessing فراخوانی گردد، این callback در سمت کدهای استفاده کننده، فراخوانی خواهد شد. مثلا توسط مقدار آن می‌توان یک Progress bar را نمایش داد.
به علاوه روش دیگری را در مورد لغو یک عملیات در اینجا ملاحظه می‌کنید. متد ThrowIfCancellationRequested نیز سبب خاتمه‌ی عملیات می‌گردد؛ البته اگر در کدهای برنامه در جایی متد Cancel توکن، فراخوانی گردد. برای مثال یک دکمه‌ی لغو عملیات در صفحه قرارگیرد و کار آن صرفا فراخوانی cts.Cancel باشد.
اشتراک‌ها
Visual Studio 2019 version 16.0.4 منتشر شد

Issues fixed in Visual Studio 2019 version 16.0.4

Security Advisory Notices

CVE-2019-0727 Diagnostics Hub Standard Collector Service Elevation of Privilege Vulnerability

An elevation of privilege vulnerability exists when the Diagnostics Hub Standard Collector Service improperly performs certain file operations. An attacker who successfully exploited this vulnerability could delete files in arbitrary locations. To exploit this vulnerability, an attacker would require unprivileged access to a vulnerable system. The security update addresses the vulnerability by securing locations the Diagnostics Hub Standard Collector performs file operations in. 

Visual Studio 2019 version 16.0.4 منتشر شد
اشتراک‌ها
1.Visual Studio 2017 15.7 منتشر شد

These are the customer-reported issues addressed in 15.7.1:

  • This release includes a fix that reduces memory usage and GC pressure during solution load.

Microsoft Security Advisory for .NET Core Denial Of Service Vulnerability

CVE-2018-0765

Microsoft is releasing this security advisory to provide information about a vulnerability in .NET Core and .NET native version 2.0. This advisory also provides guidance on what developers can do to update their applications to remove this vulnerability.

Microsoft is aware of a denial of service vulnerability that exists when .NET Framework and .NET Core improperly process XML documents. An attacker who successfully exploited this vulnerability could cause a denial of service against a .NET Framework, .NET Core, or .NET native application.

The update addresses the vulnerability by correcting how .NET Framework, .NET Core, and .NET native applications handle XML document processing.

If your application is an ASP.NET Core application, developers are also advised to update to ASP.NET Core 2.0.8. 

1.Visual Studio 2017 15.7 منتشر شد
مطالب
کار با اسکنر در برنامه های تحت وب (قسمت دوم و آخر)

در قسمت قبل « کار با اسکنر در برنامه‌های تحت وب (قسمت اول) » دیدی از کاری که قرار است انجام دهیم، رسیدیم. حالا سراغ یک پروژه‌ی عملی و پیاده سازی مطالب مطرح شده می‌رویم.

ابتدا پروژه‌ی   WCF را شروع می‌کنیم. ویژوال استودیو را باز کرده و از قسمت New Project > Visual C# > WCF یک پروژه‌ی WCF Service Application جدید را مثلا با نام "WcfServiceScanner" ایجاد نمایید. پس از ایجاد، دو فایل IService1.cs و Service1.scv موجود را به IScannerService و ScannerService تغییر نام دهید. سپس ابتدا محتویات کلاس اینترفیس IScannerService را به صورت زیر تعریف نمایید :

    [ServiceContract]
    public interface IScannerService
    {
        [OperationContract]
        [WebInvoke(Method = "GET",
           BodyStyle = WebMessageBodyStyle.Wrapped,
           RequestFormat = WebMessageFormat.Json,
           ResponseFormat = WebMessageFormat.Json,
           UriTemplate = "GetScan")]
        string GetScan();
    }
در اینجا ما فقط اعلان متدهای مورد نیاز خود را ایجاد کرده‌ایم. علت استفاده از Attribute ایی با نام WebInvoke ، مشخص نمودن نوع خروجی به صورت Json است و همچنین عنوان آدرس مناسبی برای صدا زدن متد. پس از آن کلاس ScannerService را مطابق کدهای زیر تغییر دهید:
    public class ScannerService : IScannerService
    {
        public string GetScan()
        {
            // TODO Add code here
        }
    }
تا اینجا فقط یک WCF Service معمولی ساخته‌ایم .در ادامه به سراغ کلاس WIA برای ارتباط با اسکنر می‌رویم.
بر روی پروژه‌ی خود راست کلیک کرده و Add Reference را انتخاب نموده و سپس در قسمت COM، گزینه‌ی Microsoft Windows Image Acquisition Library v2.0 را به پروژه‌ی خود اضافه نمایید.
با اضافه شدن این ارجاع به پروژه، دسترسی به فضای نام WIA برای ما امکان پذیر می‌شود که ارجاعی از آن را در کلاس ScannerService قرار می‌دهیم.
using WIA;
اکنون متد GetScan را مطابق زیر اصلاح می‌نماییم:
        public string GetScan()
        {
            var imgResult = String.Empty;
            var dialog = new CommonDialogClass();
            try
            {
                // نمایش فرم پیشفرض اسکنر
                var image = dialog.ShowAcquireImage(WiaDeviceType.ScannerDeviceType);
                
                // ذخیره تصویر در یک فایل موقت
                var filename = Path.GetTempFileName();
                image.SaveFile(filename);
                var img = Image.FromFile(filename);

                // img جهت ارسال سمت کاربر و نمایش در تگ Base64 تبدیل تصویر به 
                imgResult = ImageHelper.ImageToBase64(img, ImageFormat.Jpeg);
            }
            catch
            {
                // از آنجاییه که امکان نمایش خطا وجود ندارد در صورت بروز خطا رشته خالی 
                // بازگردانده می‌شود که به معنای نبود تصویر می‌باشد
            }

            return imgResult;
        }
دقت داشته باشید که کدها را در زمان توسعه بین Try..Catch قرار ندهید چون ممکن‌است در این زمان به خطاهایی برخورد کنید که نیاز باشد در مرورگر آنها را دیده و رفع خطا نمایید.
CommonDialogClass  کلاس اصلی در اینجا جهت نمایش فرم کار با اسکنر می‌باشد و متد‌های مختلفی را جهت ارتباط با اسکنر در اختیار ما قرار می‌دهد که بسته به نیاز خود می‌توانید از آنها استفاده کنید. برای نمونه در مثال ما نیز متد اصلی که مورد استفاده قرار گرفته، ShowAcquireImage می‌باشد که این متد، فرم پیش فرض دریافت اسکنر را به کاربر نمایش می‌دهد و کاربر از طریق آن می‌تواند قبل از شروع اسکن، یکسری تنظیمات را انجام دهد.
این متد ابتدا به صورت خودکار فرم تعیین دستگاه اسکنر ورودی را نمایش داده :


و سپس فرم پیش فرض اسکنر‌های TWAIN را جهت تعیین تنظیمات اسکن نمایش می‌دهد که این امکان نیز در این فرم فراهم است تا دستگاه‌های Feeder یا Flated انتخاب گردند.

خروجی این متد همان عکس اسکن شده است که از نوع WIA.ImageFile می‌باشد و ما پس از دریافتش، ابتدا آن را در یک فایل موقت ذخیره نموده و سپس با استفاده از یک متد کمکی آن را به فرمت Base64 برای درخواست کننده اسکن ارسال می‌نماییم.

کدهای کلاس کمکی ImageHelper:

        public static string ImageToBase64(Image image, System.Drawing.Imaging.ImageFormat format)
        {
            if (image != null)
            {
                using (MemoryStream ms = new MemoryStream())
                {
                    // Convert Image to byte[]
                    image.Save(ms, format);
                    byte[] imageBytes = ms.ToArray();

                    // Convert byte[] to Base64 String
                    string base64String = Convert.ToBase64String(imageBytes);
                    return base64String;
                }
            }
            return String.Empty;
        }
توجه داشته باشید که خروجی این متد قرار است توسط callBack یک متد جاوا اسکریپتی مورد استفاده قرار گرفته و احیانا عکس مورد نظر در صفحه نمایش داده شود. پس بهتر است که از قالب تصویر به شکل Base64 استفاده گردد. ضمن اینکه پلاگین‌های Jquery مرتبط با ویرایش تصویر هم از این قالب پشتیبانی می‌کنند. (اینجا )

این مثال به ساده‌ترین شکل نوشته شد. کلاس دیگری هم در اینجا وجود دارد و در صورتیکه از اسکنر نوع Feeder استفاده می‌کنید، می‌توانید از کدهای آن استفاده کنید.

کار ما تا اینجا در پروژه‌ی WCF Service تقریبا تمام است. اگر پروژه را یکبار Build نمایید برای اولین بار احتمالا پیغام خطاهای زیر ظاهر خواهند شد:


جهت رفع این خطا، در قسمت Reference‌های پروژه خود، WIA را انتخاب نموده و از Properties‌های آن خصوصیت Embed Interop Types را به False تغییر دهید؛ مشکل حل می‌شود.

به سراغ پروژه‌ی ویندوز فرم جهت هاست کردن این WCF سرویس می‌رویم. می‌توانید این سرویس را بر روی یک Console App یا Windows Service هم هاست کنید که در اینجا برای سادگی مثال، از WinForm استفاده می‌کنیم.
یک پروژه‌ی WinForm جدید را ایجاد کنید و سپس از قسمت Add Reference > Solution به مسیر پروژه‌ی قبلی رفته و dll‌‌های آن را به پروژه خود اضافه نمایید.
Form1.cs  را باز کرده و ابتدا دو متغیر زیر را در آن به صورت عمومی تعریف نمایید:
        private readonly Uri _baseAddress = new Uri("http://localhost:6019");
        private ServiceHost _host;
برای استفاده از کلاس ServiceHost لازم است تا ارجاعی به فضای نام System.ServiceModel داده شود. متغیر baseAddress_ نگه دارنده‌ی آدرس ثابت سرویس اسکنر در سمت کلاینت می‌باشد و به این ترتیب ما دقیقا می‌دانیم باید سرویس را با کدام آدرس در کدهای جاوا اسکریپتی خود فراخوانی نماییم.
حال در رویداد Form_Load برنامه، کدهای زیر را جهت هاست کردن سرویس اضافه می‌نماییم:
        private void Form1_Load(object sender, EventArgs e)
        {
            _host = new ServiceHost(typeof(WcfServiceScanner.ScannerService), _baseAddress);
            _host.Open();
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            _host.Close();
        }
همین چند خط برای هاست کردن سرویس روی آدرس localhost و پورت 8010 کامپیوتر کلاینت کافی است. اما یکسری تنظیمات مربوط به خود سرویس هم وجود دارد که باید در زمان پیاده سازی سرویس، در خود پروژه‌ی سرویس، ایجاد می‌گردید. اما از آنجا که ما قرار است سرویس را در یک پروژه‌ی دیگر هاست کنیم، بنابراین این تنظیمات را باید در همین پروژه‌ی WinForm قرار دهیم.
فایل App.Config پروژه‌ی WinForm را باز کرده و کدهای آنرا مطابق زیر تغییر دهید:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>

  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="BehaviourMetaData">
          <serviceMetadata httpGetEnabled="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <service name="WcfServiceScanner.ScannerService"
               behaviorConfiguration="BehaviourMetaData">
        <endpoint address=""
                  binding="basicHttpBinding"
                  contract="WcfServiceScanner.IScannerService" />
      </service>
    </services>
  </system.serviceModel>

</configuration>
اکنون پروژه‌ی هاست آماده اجرا می‌باشد. اگر آنرا اجرا کنید و در مرورگر خود آدرس ذکر شده را وارد کنید، صفحه‌ی زیر را مشاهده خواهد کرد که به معنی صحت اجرای سرویس اسکنر می‌باشد.

اگر موفق به اجرا نشدید و احیانا با خطای زیر مواجه شدید، اطمینان حاصل کنید که ویژوال استودیو Run as Administrator باشد. مشکل حل خواهد شد.


به سراغ پروژه‌ی بعدی، یعنی وب سایت خود می‌رویم. یک پروژه‌ی MVC جدید ایجاد نمایید و در View مورد نظر خود، کدهای زیر را جهت صدا زدن متد GetScan اضافه می‌کنیم.
( از آنجا که کدها به صورت جاوا اسکریپت می‌باشد، پس مهم نیست که حتما پروژه MVC باشد؛ یک صفحه‌ی HTML ساده هم کافی است).
<a href="#" id="get-scan">Get Scan</a>
<img src="" id="img-scanned" />
<script>
    $("#get-scan").click(function () {
        var url = 'http://localhost:6019/';
        $.get(url, function (data) {
            $("#img-scanned").attr("src","data:image/Jpeg;base64,  "+ data.GetScanResult);
        });
    });
</script>
دقت کنید در هنگام دریافت اطلاعات از سرویس، نتیجه به شکل GetScanResult خواهد بود. الان اگر پروژه را اجرا نمایید و روی لینک کلیک کنید، اسکنر شروع به دریافت اسکن خواهد کرد اما نتیجه‌ای بازگشت داده نخواهد شد و علت هم مشکل امنیتی CORS می‌باشد که به دلیل دریافت اطلاعات از یک دامین دیگر رخ می‌دهد و اگر با Firebug درخواست را بررسی کنید متوجه خطا به شکل زیر خواهید شد.


راه حل‌های زیادی برای این مشکل ارائه شده است، و متاسفانه بسیاری از آنها در شرایط پروژه‌ی ما جوابگو نمی‌باشد (به دلیل هاست روی یک پروژه ویندوزی). تنها راه حل مطمئن (تست شده) استفاده از یک کلاس سفارشی در پروژه‌ی WCF Service  می‌باشد که مثال آن در اینجا آورده شده است.
برای رفع مشکل به پروژه WcfServiceScanner بازگشته و کلاس جدیدی را به نام CORSSupport ایجاد کرده و کدهای زیر را به آن اضافه کنید:
    public class CORSSupport : IDispatchMessageInspector
    {
        Dictionary<string, string> requiredHeaders;
        public CORSSupport(Dictionary<string, string> headers)
        {
            requiredHeaders = headers ?? new Dictionary<string, string>();
        }

        public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
        {
            var httpRequest = request.Properties["httpRequest"] as HttpRequestMessageProperty;
            if (httpRequest.Method.ToLower() == "options")
                instanceContext.Abort();
            return httpRequest;
        }

        public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
        {
            var httpResponse = reply.Properties["httpResponse"] as HttpResponseMessageProperty;
            var httpRequest = correlationState as HttpRequestMessageProperty;

            foreach (var item in requiredHeaders)
            {
                httpResponse.Headers.Add(item.Key, item.Value);
            }
            var origin = httpRequest.Headers["origin"];
            if (origin != null)
                httpResponse.Headers.Add("Access-Control-Allow-Origin", origin);

            var method = httpRequest.Method;
            if (method.ToLower() == "options")
                httpResponse.StatusCode = System.Net.HttpStatusCode.NoContent;

        }
    }

    // Simply apply this attribute to a DataService-derived class to get
    // CORS support in that service
    [AttributeUsage(AttributeTargets.Class)]
    public class CORSSupportBehaviorAttribute : Attribute, IServiceBehavior
    {
        #region IServiceBehavior Members

        void IServiceBehavior.AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
        {
        }

        void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            var requiredHeaders = new Dictionary<string, string>();

            //Chrome doesn't accept wildcards when authorization flag is true
            //requiredHeaders.Add("Access-Control-Allow-Origin", "*");
            requiredHeaders.Add("Access-Control-Request-Method", "POST,GET,PUT,DELETE,OPTIONS");
            requiredHeaders.Add("Access-Control-Allow-Headers", "Accept, Origin, Authorization, X-Requested-With,Content-Type");
            requiredHeaders.Add("Access-Control-Allow-Credentials", "true");
            foreach (ChannelDispatcher cd in serviceHostBase.ChannelDispatchers)
            {
                foreach (EndpointDispatcher ed in cd.Endpoints)
                {
                    ed.DispatchRuntime.MessageInspectors.Add(new CORSSupport(requiredHeaders));
                }
            }
        }

        void IServiceBehavior.Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
        }

        #endregion
    }
فضاهای نام لازم برای این کلاس به شرح زیر می‌باشد:
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
کلاس ScannerService را باز کرده و آنرا به ویژگی
    [CORSSupportBehavior]
    public class ScannerService : IScannerService
    {
مزین نمایید.

کار تمام است، یکبار دیگر ابتدا پروژه‌ی WcfServiecScanner و سپس پروژه هاست را Build کرده و برنامه‌ی هاست را اجرا کنید. اکنون مشاهده می‌کنید که با زدن دکمه‌ی اسکن، اسکنر فرم تنظیمات اسکن را نمایش می‌دهد که پس از زدن دکمه‌ی Scan، پروسه آغاز شده و پس از اتمام، تصویر اسکن شده در صفحه‌ی وب سایت نمایش داده می‌شود.
مطالب
NoSQL و مایکروسافت
روشی را که مایکروسافت برای پرداختن به مقوله NoSQL تاکنون انتخاب کرده است، قرار دادن ویژگی‌هایی خاصی از دنیای NoSQL مانند امکان تعریف اسکیمای متغیر، داخل مهم‌ترین بانک اطلاعاتی رابطه‌ای آن، یعنی SQL Server است، که در ادامه به آن خواهیم پرداخت. همچنین در سمت محصولات پردازش ابری آن نیز امکان دسترسی به محصولات NoSQL کاملی وجود دارد.

1) Azure table storage
Azure table storage در حقیقت یک Key-value store ابری است و برای کار با آن از اینترفیس پروتکل استاندارد OData استفاده می‌شود. علت استفاده و طراحی یک سیستم Key-value store در اینجا، مناسب بودن اینگونه سیستم‌ها جهت مقاصد عمومی است و به این ترتیب می‌توان به بازه بیشتری از مصرف کنندگان، خدمات ارائه داد.
پیش از ارائه Azure table storage، مایکروسافت سرویس خاصی را به نام SQL Server Data Services که به آن SQL Azure نیز گفته می‌شود، معرفی کرد. این سرویس نیز یک Key-Value store است؛ هرچند از SQL Server به عنوان مخزن نگهداری اطلاعات آن استفاده می‌کند.


2) SQL Azure XML Columns
فیلدهای XML از سال 2005 به امکانات توکار SQL Server اضافه شدند و این نوع فیلدها، بسیاری از مزایای دنیای NoSQL را درون SQL Server رابطه‌ای مهیا می‌سازند. برای مثال با تعریف یک فیلد به صورت XML، می‌توان از هر ردیف به ردیفی دیگر، اطلاعات متفاوتی را ذخیره کرد؛ به این ترتیب امکان کار با یک فیلد که می‌تواند اطلاعات یک شیء را قبول کند و در حقیقت امکان تعریف اسکیمای پویا و متغیر را در کنار امکانات یک بانک اطلاعاتی رابطه‌ای که از اسکیمای ثابت پشتیبانی می‌کند، میسر می‌شود. در این حالت در هر ردیف می‌توان تعدادی ستون ثابت را با یک ستون XML با اسکیمای کاملا پویا ترکیب کرد.
همچنین SQL Server در این حالت قابلیتی را ارائه می‌دهد که در بسیاری از بانک‌های اطلاعاتی NoSQL میسر نیست. در اینجا در صورت نیاز و لزوم می‌توان اسکیمای کاملا مشخصی را به یک فیلد XML نیز انتساب داد؛ هر چند این مورد اختیاری است و می‌توان یک un typed XML را نیز بکار برد. به علاوه امکانات کوئری گرفتن توکار از این اطلاعات را به کمک XPath ترکیب شده با T-SQL، نیز فراموش نکنید.
بنابراین اگر یکی از اهداف اصلی گرایش شما به سمت دنیای NoSQL، استفاده از امکان تعریف اطلاعاتی با اسکیمای متغیر و پویا است، فیلدهای نوع XML اس کیوال سرور را مدنظر داشته باشید.
یک مثال عملی: فناوری Azure Dev Fabric's Table Storage (نسخه Developer ویندوز Azure که روی ویندوزهای معمولی اجرا می‌شود؛ یک شبیه ساز خانگی) به کمک SQL Server و فیلدهای XML آن طراحی شده است.


3) SQL Azure Federations
در اینجا منظور از Federations در حقیقت همان پیاده سازی قابلیت Sharding بانک‌های اطلاعاتی NoSQL توسط SQL Azure است که برای توزیع اطلاعات بر روی سرورهای مختلف طراحی شده است. به این ترتیب دو قابلیت Partitioning و همچنین Replication به صورت خودکار در دسترس خواهند بود. هر Partition در اینجا، یک SQL Azure کامل است. بنابراین چندین بانک اطلاعاتی فیزیکی، یک بانک اطلاعاتی کلی را تشکیل خواهند داد.
هرچند در اینجا Sharding  (که به آن Federation member گفته می‌شود) و در پی آن مفهوم «عاقبت یک دست شدن اطلاعات» وجود دارد، اما درون یک Shard یا یک Federation member، مفهوم ACID پیاده سازی شده است. از این جهت که هر Shard واقعا یک بانک اطلاعاتی رابطه‌ای است. اینجا است که مفهوم برنامه‌های  Multi-tenancy را برای درک آن باید درنظر داشت. برای نمونه یک برنامه وب را درنظر بگیرید که قسمت اصلی اطلاعات کاربران آن بر روی یک Shard قرار دارد و سایر اطلاعات بر روی سایر Shards پراکنده شده‌اند. در این حالت است که یک برنامه وب با وجود مفهوم ACID در یک Shard می‌تواند سریع پاسخ دهد که آیا کاربری پیشتر در سایت ثبت نام کرده است یا خیر و از ثبت نام‌های غیرمجاز جلوگیری به عمل آورد.
در اینجا تنها موردی که پشتیبانی نشده‌است، کوئری‌های Fan-out می‌باشد که پیشتر در مورد آن بحث شد. از این جهت که با نحوه خاصی که Sharding آن طراحی شده است، نیازی به تهیه کوئری‌هایی که به صورت موازی بر روی کلیه Shards برای جمع آوری اطلاعات اجرا می‌شوند، نیست. هر چند از هر shard با استفاده از برنامه‌های دات نت، می‌توان به صورت جداگانه نیز کوئری گرفت.


4) OData
اگر به CouchDB و امکان دسترسی به امکانات آن از طریق وب دقت کنید، در محصولات مایکروسافت نیز این دسترسی REST API پیاده سازی شده‌اند.
OData یک RESTful API است برای دسترسی به اطلاعاتی که به شکل XML یا JSON بازگشت داده می‌شوند. انواع و اقسام کلاینت‌هایی برای کار با آن از جاوا اسکریپت گرفته تا سیستم‌های موبایل، دات نت و جاوا، وجود دارند. از این API نه فقط برای خواندن اطلاعات، بلکه برای ثبت و به روز رسانی داده‌ها نیز استفاده می‌شود. در سیستم‌های جاری مایکروسافت، بسیاری از فناوری‌ها، اطلاعات خود را به صورت OData دراختیار مصرف کنندگان قرار می‌دهند مانند Azure table storage، کار با SQL Azure از طریق WCF Data Services (جایی که OData از آن نشات گرفته شده)، Azure Data Market (برای ارائه فیدهایی از اطلاعات خصوصا رایگان)، ابزارهای گزارشگیری مانند SQL Server reporting services، لیست‌های شیرپوینت و غیره.
به این ترتیب به بسیاری از قابلیت‌های دنیای NoSQL مانند کار با اطلاعات JSON بدون ترک دنیای رابطه‌ای می‌توان دسترسی داشت.


5) امکان اجرای MongoDB و امثال آن روی سکوی کاری Azure
امکان توزیع MongoDB بر روی یک Worker role سکوی کاری Azure وجود دارد. در این حالت بانک‌های اطلاعاتی این سیستم‌ها بر روی Azure Blob Storage قرار می‌گیرند که به آن‌ها Azure drive نیز گفته می‌شود. همین روش برای سایر بانک‌های اطلاعاتی NoSQL نیز قابل اجرا است.
به علاوه امکان اجرای Hadoop نیز بر روی Azure وجود دارد. مایکروسافت به کمک شرکتی به نام HortonWorks نسخه ویندوزی Hadoop را توسعه داده‌اند. HortonWorks را افرادی تشکیل داده‌اند که پیشتر در شرکت یاهو بر روی پروژه Hadoop کار می‌کرده‌اند.


6) قابلیت‌های فرا رابطه‌ای SQL Server
الف) فیلدهای XML (که در ابتدای این مطلب به آن پرداخته شد). به این ترتیب می‌توان به یک اسکیمای انعطاف پذیر، بدون از دست دادن ضمانت ACID رسید.
ب) فیلد HierarchyId برای ذخیره سازی اطلاعات چند سطحی. برای مثال در بانک‌های اطلاعاتی NoSQL سندگرا، یک سند می‌تواند سند دیگری را در خود ذخیره کند و الی آخر.
ج) Sparse columns؛ ستون‌های اسپارس تقریبا شبیه به Key-value stores عمل می‌کنند و یا حتی Wide column stores نیز با آن قابل مقایسه است. در اینجا هنوز اسکیما وجود دارد، اما برای نمونه علت استفاده از Wide column stores این نیست که واقعا نمی‌دانید ساختار داده‌های مورد استفاده چیست، بلکه در این حالت می‌دانیم که در هر ردیف تنها از تعداد معدودی از فیلدها استفاده خواهیم کرد. به همین جهت در هر ردیف تمام فیلدها قرار نمی‌گیرند، چون در اینصورت تعدادی از آن‌ها همواره خالی باقی می‌ماندند. مایکروسافت این مشکل را با ستون‌های اسپارس حل کرده است؛ در اینجا هر چند ساختار کلی مشخص است، اما مواردی که هر بار استفاده می‌شوند، تعداد محدودی می‌باشند. به این صورت SQL Server تنها برای ستون‌های دارای مقدار، فضایی را اختصاص می‌دهد. به این ترتیب از لحاظ فیزیکی و ذخیره سازی نهایی، به همان مزیت Wide column stores خواهیم رسید.
د) FileStreams در اس کیوال سرور بسیار شبیه به پیوست‌های سندهای بانک‌های اطلاعاتی NoSQL سندگرا هستند. در اینجا نیز اطلاعات در فایل سیستم ذخیره می‌شوند اما ارجاعی به آن‌ها در جداول مرتبط وجود خواهند داشت.


7) SQL Server Parallel Data Warehouse Edition
SQL PDW، نگارش خاصی از SQL Server است که در آن یک شبکه از SQL Serverها به صورت یک وهله منطقی SQL Server در اختیار برنامه نویس‌ها قرار می‌گیرد.
این نگارش، از فناوری خاصی به نام MPP یا massively parallel processing برای پردازش کوئری‌ها استفاده می‌کند. در اینجا همانند بانک‌های اطلاعاتی NoSQL، یک کوئری به نود اصلی ارسال شده و به صورت موازی بر روی تمام نودها پردازش گردیده (همان مفهوم Map Reduce که پیشتر در مورد آن بحث شد) و نتیجه در اختیار مصرف کننده قرار خواهد گرفت. نکته مهم آن نیز در عدم نیاز به نوشتن کدی جهت رخ دادن این عملیات از طرف برنامه نویس‌ها است و موتور پردازشی آن جزئی از سیستم اصلی است. تنها کافی است یک کوئری SQL صادر گردد تا نتیجه نهایی از تمام سرورها جمع آوری و بازگردانده شود.
این نگارش ویژه تنها به صورت یک Appliance به فروش می‌رسد (به صورت سخت افزار و نرم افزار باهم) که در آن CPU‌ها، فضاهای ذخیره سازی اطلاعات و جزئیات شبکه به دقت از پیش تنظیم شده‌اند.
اشتراک‌ها
ASP.NET AJAX Control Toolkit v19.1.0 منتشر شد

A few years ago, we took over maintenance and guidance for the ASP.NET AJAX Control Toolkit project. Please refer to this blog post for more information on the project and why we stepped in to assist.
As part of our ongoing commitment to the project, we’ve released an update (ASP.NET AJAX Control Toolkit v19.1.0) to address the following issues.
Improvements
- Visual Studio 2019 Support
- Security hardening: HTML-encode file names in AjaxFileUpload (#483)
 

ASP.NET AJAX Control Toolkit v19.1.0 منتشر شد
مطالب
بخش اول - آشنایی و شروع کار با Svelte
 

svelte




معرفی : 
Svelte یک رویکرد جدید برای ایجاد رابط کاربری است که به ما کمک میکند صفحاتی پویا به صورت SPA با کارآیی و کیفیت بالا و همچنین کمترین حجم کد تولید کنیم. تفاوت اصلی svelte با رقبای سنتی خود مانند vue - React - angular  این است که Svelte تنها یک فریم ورک نیست، بلکه درواقع یک کامپایلر است که همین موضوع سبب شده توجه زیادی را اخیرا به خود جلب کند. در فریم ورک‌های سنتی، تمام عملیات در browser انجام میشود یا بهتر است بگوییم در run-time؛ ولی svelte تمام این عملیات را زمان build شدن برنامه شما انجام میدهد و کد جاوا اسکریپتی بدون هیچ وابستگی به هیچ پکیجی تولید میکند. نکته دیگری که باید به آن اشاره کنم این است که برخلاف سایر فریم ورک‌ها، svelte از virtual DOM استفاده نمیکند! در بخش‌های بعد در مورد virtual DOM و معایب آن بیشتر صحبت خواهیم کرد. 


مقایسه مختصر فریم ورک‌های معتبر :
مقایسه‌هایی که در ادامه قصد دارم به اشتراک بگذارم، بر مبنای سه بخش Performance - size - lines of code است که به صورت مختصر با هم بررسی خواهیم کرد و کاری با جزئیات این مقایسه نداریم؛ چرا که هدف از نشان دادن این مقایسه صرفا این است که شاید برای ما سوال شود چرا باید یا بهتر است به این فریم ورک اهمیت بدهیم. 

  • Performance : کارآیی - که در ارتباط با مدت زمان پاسخ گویی و قابل استفاده شدن برنامه میباشد. (مقایسه به درصد - هرچه بیشتر عملکرد بهتر)


در مقایسه اول، اکثر فریم ورک‌ها، امتیازی بالای 90 درصد دارند که در واقع نشان دهنده این است شما از هرکدام از این موارد استفاده کنید، چندان تفاوتی را احساس نخواهید کرد. 
با توجه به اینکه svelte به نسبت بقیه این فریم ورک‌ها که خیلی از آنها کاملا جا افتاده هستند، بسیار جدید است و جای بهبود دارد از نظر performance عملکرد قابل قبولی از خود نشان داده است.

  • Size : اندازه - که نشان دهنده حجم نهایی فایل‌های تولید شده ( Css-Html-JavaScript ) فریم ورک است. این مقایسه اندازه فریم ورک و تمام وابستگی‌های آن است که به bundle نهایی برنامه اضافه شده است (هر چه اندازه فایل کمتر باشد بهتر است چراکه توسط کاربر نهایی زودتر دانلود میشود).


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


  • Lines of Code : تعداد خطوط کد - نشان دهنده این است که یک نویسنده بر اساس این فریم ورک‌ها چند سطر کد را باید برای تهیه‌ی یک برنامه‌ی جدید بنویسد.


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

نتیجه گیری : ( مزایا  -  معایب  )
درمورد مزایای استفاده از svelte میتوان به راحتی کارکردن با آن، حجم بسیار کم کدهای نهایی برنامه و عملکرد مناسب آن و همینطور استفاده نکردن از virtualDom اشاره کرد؛ چرا که برای اولین بار کدهای تولید شده به معنای واقعی واکنش گرا خواهند بود.
هرچند معایبی هم شاید داشته باشد که قبل از هر چیز بهتر است به آنها اشاره کنم. بزرگترین و شاید تنها ایرادی که من میتوانم از این فناوری بگیرم این است که خالق این تکنولوژی یک نفر است! angular توسط شرکت google توسعه داده میشود. react  توسط فیسبوک توسعه داده میشود. vue درست است که شرکت بزرگی آن را توسعه نمیدهد ولی نتیجه یک کار تیمی و چند صد نفر برنامه نویس مختلف است که به صورت open source به توسعه آن میپردازند. شاید این تنها نکته منفی باشد که اعتماد به این تکنولوژی را سخت کرده است.



دانلود و نصب : 
پیش نیاز :
قبل از هرچیز برای نصب Svelte به Node.Js نیاز داریم. قبل از شروع کار، از نصب بودن آن اطمینان حاصل نمایید.
ساخت اولین برنامه : 
npx degit sveltejs/template my-svelte-project
cd my-svelte-project
npm install
npm run dev
با استفاده از degit در ابتدا اقدام به دریافت sveltejs/template میکنیم که قالب ساده‌ای برای شروع کار با svelte میباشد. سپس به فولدری که فایل‌ها در آن قرار گرفته‌اند، رفته و وابستگی‌های قالب را نصب میکنیم. در انتها با دستور npm run dev پروژه ساده HelloWorld ما به صورت پیش فرض بر روی پورت 5000 localhost قابل مشاهده است.
البته با استفاده از اسکریپت dev، کدهای ما برای زمان برنامه نویسی بهینه شده‌اند و چندان برای پابلیش و استفاده مناسب نیستند؛ لذا برای تولید کدهای مناسب برای محصول نهایی میتوانیم از دستور npm run build استفاده کنیم.
در بخش بعد به بررسی ساختار فایل‌ها و کدهای ایجاد شده Svelte میپردازیم.