نظرات مطالب
نمایش بلادرنگ اعلامی به تمام کاربران در هنگام درج یک رکورد جدید به صورت notification
پیشنهاد شما برای متوجه شدن کاربران از تغییرات انی دیتابیس چی هست؟
مثلا دیتابیس به یک دستگاهی مثل دستگاههای حضور و غیاب متصل باشه  و به محض ثبت لاگ اشخاص توسط دستگاه 
برنامه وب متوجه اون بشه  آیا SignalR بهمراه SqlDependency جوابگو هست؟
مطالب
نکته ای برای استفاده راحت تر ECMA Scripts در توسعه تحت شیرپوینت
هنگام کدنویسی زبان‌های سمت کاربر (Client Side)  اگر به عنوان برنامه نویس و توسعه دهنده ، با کتابخانه‌های آن آشنا 
باشید و آنها را حفظ باشید خیلی خوب است ولی اگر همین کتابخانه‌ها و توابع به ابعاد شیرپوینت گسترش یابد چه؟ مسلما حفظ کردن تمام آنها کار دشواری است ؛ راه حلی که در اینجا ارائه می‌شود ،بار گذاری این توابع در Intellisense  ویژوال استودیو است . برای این کار در صورتی که در حال نوشتن Visual WebPart هستید ، می‌توانیدبه روش زیر عمل کنید :  

ابتدا بالای صفحه مورد نظر کد زیر را وارد کنید : 
<% #if SOME_UNDEFINED_CONSTANT %>
 <script type="text/javascript" src="/_layouts/MicrosoftAjax.js" ></script>
 <script type="text/javascript" src="/_layouts/SP.debug.js"></script>
<% #endif %>
در این لحظه ویژوال استودیو آغاز به روز رسانی متادیتای Intellisense  خود می‌کند که می‌توانید این پیغام را در زیر نوار وضعیت این برنامه مشاهده کنید . 



حال می‌توانید به راحتی از این امکانات لذت ببرید و به توسعه خود سرعت دهید.

نظرات مطالب
ایجاد alert,confirm,prompt هایی متفاوت با jQuery Impromptu
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" media="all" type="text/css" href="http://trentrichardson.com/Impromptu/jquery-impromptu.css" />
<script type="text/javascript" src="http://code.jquery.com/jquery-1.9.0.min.js"></script>
<script type="text/javascript" src="http://trentrichardson.com/Impromptu/jquery-impromptu.js"></script>
</head>
<body>
<button class="show">ShowPrompt</button>
<script type="text/javascript">
$(function(){
   $(".show").click(function(e){
      $.prompt("Hello World!");
   });
});
</script>
</body>
</html>

نظرات مطالب
آشنایی با WebDav و نحوه استفاده از آن
سلام. با تشکر از آموزش و تهیه کتابخونه.

وقتی فایل رو با word باز میکنم، بصورت readonly باز میشه و گزینه save بصورت آیکن sync نیست.
هم توی نمونه سورس کد گیت و هم یک وب‌اپ که خودم ایجاد کردم و رفرنس و پکیج نصب کردم مشکل بود. روی iis هم پابلیش گذاشتم فرقی نکرد.
مطالب
سازگارسازی کلاس‌های اعتبارسنجی Twitter Bootstrap 3 با فرم‌های ASP.NET MVC
چندی پیش در همین وب‌سایت مطلبی تحت عنوان «اعمال کلاس‌های ویژه اعتبارسنجی Twitter bootstrap به فرم‌های ASP.NET MVC» منتشر شد. این مقاله مرتبط با نسخه دوم فریم‌ورک محبوب Bootstrap بود. قصد داریم به بازنویسی کدهای مرتبط بپردازیم و کلاس‌های مرتبط با نسخه سوم این فریم‌ورک را هم با فرم‌های خودمان سازگار کنیم. مثل مقاله‌ی ذکر شده توضیحات را با یک مثال همراه می‌کنم.

مدل برنامه
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace FormValidationWithBootstrap.Models
{
    [Table("Product")]
    public class ProductModel
    {
        [Key]
        public int Id { get; set; }
        [Required(ErrorMessage = "{0} یک فیلد اجباری است و باید آن را وارد کنید.")]
        [StringLength(50, ErrorMessage = "طول {0} باید کمتر از {1} کاراکتر باشد.")]
        [Display(Name = "نام کالا")]
        public string Name { get; set; }
        [Required(ErrorMessage = "{0} یک فیلد اجباری است و باید آن را وارد کنید.")]
        [Display(Name = "قیمت")]
        [DataType(DataType.Currency)]
        public double Price { get; set; }
        [Required(ErrorMessage = "{0} یک فیلد اجباری است و باید آن را وارد کنید.")]
        [Display(Name = "موجودی")]
        public int Qty { get; set; }
    }
}
قرار هست که جدولی داشته باشیم با نام Product برای ثبت محصولات. مدل برنامه شامل خاصیت‌های مرتبط و همچنین اعتبارسنجی‌های مد نظر ما هست.

کنترلر برنامه
using System.Web.Mvc;
using FormValidationWithBootstrap.Models;

namespace FormValidationWithBootstrap.Controllers
{
    public class ProductController : Controller
    {
        // GET: Product
        public ActionResult Index()
        {
            return View();
        }

        public ActionResult New()
        {
            return View();
        }

        [HttpPost]
        public ActionResult New(ProductModel product)
        {
            if (!ModelState.IsValid)
                return View(product);

            if (product.Name != "پفک")
            {
                ModelState.AddModelError("", "لطفا مشکلات را برطرف کنید!");
                ModelState.AddModelError("Name", "فقط محصولی با نام پفک قابل ثبت است :)");
                return View(product);
            }
            // todo:save...
            return RedirectToAction("Index");
        }
    }
}
در قسمت کنترلر نیز اتفاق خاصی نیفتاده و کارهای پایه فقط انجام شده؛ ضمن اینکه آمدیم برای داشتن خطاهای سفارشی نام محصول را چک کردیم و گفتیم اگر نام محصول چیزی غیر از «پفک» بود، از سمت سرور خطایی را صادر کند و بگوید که فقط پفک قابل ثبت هست.

View برنامه
@model FormValidationWithBootstrap.Models.ProductModel
@{
    ViewBag.Title = "New";
}
<h2>کالای جدید</h2>
@using (Html.BeginForm()) 
{
    @Html.AntiForgeryToken()
    <div>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "alert alert-danger" })
        <div>
            @Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
            <div>
                @Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
            </div>
        </div>
        <div>
            @Html.LabelFor(model => model.Price, htmlAttributes: new { @class = "control-label col-md-2" })
            <div>
                @Html.EditorFor(model => model.Price, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Price, "", new { @class = "text-danger" })
            </div>
        </div>
        <div>
            @Html.LabelFor(model => model.Qty, htmlAttributes: new { @class = "control-label col-md-2" })
            <div>
                @Html.EditorFor(model => model.Qty, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Qty, "", new { @class = "text-danger" })
            </div>
        </div>
        <div>
            <div>
                <input type="submit" value="ثبت" />
                <input type="reset" value="ریست" />
                @Html.ActionLink("بازگشت به لیست", "Index", "Product", null, new {@class="btn btn-default"})
            </div>
        </div>
    </div>
}
فایل View برنامه با Scafflod Templateها ساخته شده و چون از Visual Studio 2013 استفاده شده، به‌صورت پیش‌فرض با بوت‌استرپ سازگار هست. تغییری که ایجاد شده تعویض کلاس مربوط به ValidationSummary هست که به alert alert-danger تغییر پیدا کرده و همچین دو دکمه «ریست» و «بازگشت به لیست» هم به کنار دکمه «ثبت» اضافه شده.

در فرم بالا شاهد هستیم که با کلیک بر روی دکمه ثبت تنها خطاهای مرتبط با هر ردیف ظاهر شده‌اند و هیچ تغییر رنگی که حاصل از کلاس‌های مرتبط با Bootstrap باشند حاصل نشده. برای رفع این مشکل کافی‌‌است اسکریپت زیر، به انتهای فایل View برنامه اضافه شود تا پیش‌فرض‌های jQuery Validator را تغییر دهیم و آن‌ها را با بوت‌استرپ سازگار کنیم. همچنین در حالت ارسال فرم به سرور و Postback و نمایش خطاهای سفارشی، قسمت بررسی field-validation-error صورت می‌گیرد و در صورتیکه موردی را پیدا کند، به سطر مرتبط با آن کلاس has-error اضافه خواهد شد. 
@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
    <script>
        // override jquery validate plugin defaults
        $.validator.setDefaults({
            highlight: function (element) {
                $(element).closest('.form-group').addClass('has-error');
            },
            unhighlight: function (element) {
                $(element).closest('.form-group').removeClass('has-error').addClass('has-success');
            },
            errorElement: 'span',
            errorClass: 'help-block',
            errorPlacement: function (error, element) {
                if (element.parent('.input-group').length) {
                    error.insertAfter(element.parent());
                } else {
                    error.insertAfter(element);
                }
            }
        });
        $(function () {
            $('form').each(function () {
                $(this).find('div.form-group').each(function () {
                    if ($(this).find('span.field-validation-error').length > 0) {
                        $(this).addClass('has-error');
                    }
                });
            });
        });
    </script>
}

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

همچنین هنگامیکه کاربر فیلد را به درستی وارد کرد، رنگ فیلد و همچین آن ردیف به سبز تغییر خواهد کرد.

و همچنین در حالت رخ‌داد یک خطای سفارشی پس از postback از سمت سرور به حالت زیر خواهیم رسیذ.

کدهای کامل این مثال را از اینجا می‌توانید دریافت کنید 

FormValidationWithBootstrap.rar 

اشتراک‌ها
دریافت کتاب SignalR Programming in Microsoft ASP.NET انتشارات مایکروسافت
این کتاب یک راهنمای دقیق برای SignalR است؛ SignalR یک کتاب خانه‌ی جدید برای توسعه دهندگان ASP.NET است که روند توسعه‌ی برنامه‌های تحت وب بلادرنگ را آسان می‌کند. قابلیت بلادرنگی در وب، سرور را قادر می‌سازد تا محتویات مورد نظرش را به بدون وقفه در لحظه ای که کلاینت‌ها به آن متصل می‌شوند ارسال نماید. در این کتاب توسعه دهندگان Microsoft .NET که با HTML و JavaScript آشنایی دارند، به توانایی توسعه برنامه‌های بلادرنگ و ارتباطات نا متقارن تحت وب، دسکتاپ و گوشی‌های موبایل دست پیدا می‌کنند. 
دریافت کتاب SignalR Programming in Microsoft ASP.NET انتشارات مایکروسافت
مطالب
معماری میکروسرویس‌ها
برنامه‌های بزرگ سمت سرور که با تعداد بسیار زیادی کاربر و داده سر و کار دارند، نباید فقط درگیر پاسخگویی سریع و فراهم کردن وب سرویس‌ها برای پلت‌فرم‌های مختلف باشند. این برنامه‌ها باید بتوانند به سادگی رشد کرده، ارتقاء پیدا کنند و به روز شوند. برای ساخت و توسعه این نوع برنامه‌ها، دو مدل معماری وجود دارد: یکی  معماری Monolithic و دیگری معماری Microservices. برای شناخت معماری Microservices، ابتدا بایستی با معماری Monolithic آشنا شد.


 معماری Monolithic چیست؟ 

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


مشکلات معماری Monolithic

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

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


معماری Microservices

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

 در دیاگرام بالا میشود اینطور تصور کرد که Service1، یک وب سرور است که با مرورگر برای دریافت درخواست‌ها در ارتباط است و باقی سرویس‌ها حکم API  برای عملیات‌های مختلف را دارند. 


 ارزش معماری Microservices

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


افزایش یک سرویس خاص

 یکی از با ارزش‌ترین قابلیت‌های معماری Microservices، افزایش یک سرویس، که به عنوان مثال فقط یک وهله از آن در حال اجراست، به دو یا سه وهله جداگانه است؛ بدون آنکه نیاز باشد سرویس‌های در ارتباط با آنها نیز وهله سازیهای اضافه‌ای داشته باشند. این حالت در دیاگرام زیر قابل مشاهده است. 

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


مشکلات معماری Microservices

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


چه زمانی از معماری Microservices استفاده کنیم؟

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

 

 مدیریت داده‌ها: 

در معماری Microservices، هر سرویس می‌تواند پایگاه داده خود را برای ذخیره داده‌ها داشته باشد و یا اینکه از یک پایگاه داده مرکزی بهره ببرد. استفاده از پایگاه داده‌ی مجزای برای هر سرویس، مشکلات خود را دارد. باید بین سرویس‌های مختلف، همگام سازی صورت بگیرد که در این صورت، اگر یکی از سرویس‌ها از کار بیافتد، سرویس‌های وابسته به آن که داده‌ها بین آنها در تبادل هستند، دچار مشکل می‌شود و مسئله می‌تواند به سایر سرویس‌ها که به صورت زنجیر وار به داده‌های در حال تبادل یکدیگر وابسته هستند، سرایت کند. همچنین در این روش داده‌های تکراری وجود خواهند داشت و در نهایت کدنویسی برای این سیستم مشکل خواهد بود. 
در نتیجه بهتر این است که سرویس‌ها با یک پایگاه داده مرکزی سر و کار داشته باشند و اگر سرویس خاصی نیاز داشته باشد که داده‌های بخصوص خود را تولید کند و نمی‌خواهد آن را با سایر سرویس‌ها به اشتراک بگذارد، می‌تواند پایگاه داده مخصوص به خود را داشته باشد. نکته مهم دیگر این است که سرویس‌ها نباید به صورت مستقیم با پایگاه داده مرکزی در ارتباط باشند؛ بلکه به سرویسی مجزا، به نام "سرویس پایگاه داده" که وظیفه فراهم کردن API‌های مخصوص کار با پایگاه داده مرکزی را به عهده دارد، نیاز است.


پیاده‌سازی معماری Microservices‌ها توسط فریم‌فرک Seneca

Seneca یک فریم ورک Node.js است که برای ساخت برنامه‌های سمت سروری با معماری Microservices و هسته Monolithic استفاده می‌شود. در مطلب بعدی به این فریم‌ورک نگاهی گذرا خواهیم داشت.
نظرات مطالب
ASP.NET MVC #11
سلام،
چند عدد سوال داشتم:

1- از آنجایی که بنده در مورد استفاده کمتر از منابع سرور و ... خیلی حساسم و در پی یافتن بهینه‌ترین روش کدینگ هستم ، سوالی برام پیش اومده :
 آیا تعریف یک پراپرتی با دسترسی private  از نوع EntityFrameWorkContext در سطح کلاس کنترلر (یا سطح کلاس سرویس یا کلا در سطح یک کلاس) و استفاده از آن در متدهای کلاس و استفاده نکردن از using در داخل متدها از نظر حرفه ای درست می‌باشد ؟
(این روش رو در چند جا مشاهده کردم و شک کردم که نکنه روش بنده که همیشه using می‌زنم بهینه نیست....)
{بهترین روش چیه ؟}

2- اگر از استفاده غیرضروری از منابع سرور صرف نظر کنیم ؛ اگر ما ViewModel استفاده نکنیم و درون اکشن‌های ویرایش مثلا اینجوری کد بزنیم :

public ActionResult Edit(Member member)
{
var updatedItem = db.Members.FirstOrDefault(c => c.id == 1);

updatedItem.Name = member.Name;
updatedItem.Family = member.Family;

db.saveChanges();

return View();

}
آیا به دلیل استفاده نکردن از پراپرتی‌های غیر ضروری ، مشکل امنیتی برطرف میشه ؟
(بدین صورت اگر کاربر شیطونی کنه و مثلا فیلدای IsAdmin رو دستی بسازه و .... ازش استفاده نمیشه و مشکلی پیش نمیاد)
(نهایتا Model.IsValid هم می‌تونیم در اینجا استفاده کنیم)

مسلما موقع ثبت هم مقدار پروپرتی‌های حساس رو خودمون دستی پر می‌کنیم و اصلا کاری به ورودی دریافتی اکشن نخواهیم داشت.
public ActionResult Create(Member member)
{

If (Model.IsValid)
{

   db.Members.AddObject(new Member{ Name = member.Name , Family = member.Family , IsAdmin = False});
   db.saveChanges();

// ...

}

return View();

}

3- سفارشی سازی پیام‌های خطای اعتبار سنجی فرم رو هم من که تست کردم ، همش انگلیسی پیام میده!
و متن فارسی منو نادیده می‌گیره ...
یک توضیح بیشتر اگر مرحمت کنین ، ممنون میشم.

با تشکر
مطالب
تولید هدرهای Content Security Policy توسط ASP.NET Core برای برنامه‌های Angular
پیشتر مطلب «افزودن هدرهای Content Security Policy به برنامه‌های ASP.NET» را در این سایت مطالعه کرده‌اید. در اینجا قصد داریم معادل آن‌را برای ASP.NET Core تهیه کرده و همچنین نکات مرتبط با برنامه‌های Angular را نیز در آن لحاظ کنیم.


تهیه میان افزار افزودن هدرهای Content Security Policy

کدهای کامل این میان افزار را در ادامه مشاهده می‌کنید:
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;

namespace AngularTemplateDrivenFormsLab.Utils
{
    public class ContentSecurityPolicyMiddleware
    {
        private readonly RequestDelegate _next;

        public ContentSecurityPolicyMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        public Task Invoke(HttpContext context)
        {
            context.Response.Headers.Add("X-Frame-Options", "SAMEORIGIN");
            context.Response.Headers.Add("X-Xss-Protection", "1; mode=block");
            context.Response.Headers.Add("X-Content-Type-Options", "nosniff");

            string[] csp =
            {
              "default-src 'self'",
              "style-src 'self' 'unsafe-inline'",
              "script-src 'self' 'unsafe-inline' 'unsafe-eval'",
              "font-src 'self'",
              "img-src 'self' data:",
              "connect-src 'self'",
              "media-src 'self'",
              "object-src 'self'",
              "report-uri /api/CspReport/Log" //TODO: Add api/CspReport/Log
            };
            context.Response.Headers.Add("Content-Security-Policy", string.Join("; ", csp));
            return _next(context);
        }
    }

    public static class ContentSecurityPolicyMiddlewareExtensions
    {
        /// <summary>
        /// Make sure you add this code BEFORE app.UseStaticFiles();,
        /// otherwise the headers will not be applied to your static files.
        /// </summary>
        public static IApplicationBuilder UseContentSecurityPolicy(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<ContentSecurityPolicyMiddleware>();
        }
    }
}
که نحوه‌ی استفاده از آن در کلاس آغازین برنامه به صورت ذیل خواهد بود:
public void Configure(IApplicationBuilder app)
{
   app.UseContentSecurityPolicy();

توضیحات تکمیلی

افزودن X-Frame-Options
 context.Response.Headers.Add("X-Frame-Options", "SAMEORIGIN");
از هدر X-FRAME-OPTIONS، جهت منع نمایش و رندر سایت جاری، در iframeهای سایت‌های دیگر استفاده می‌شود. ذکر مقدار SAMEORIGIN آن، به معنای مجاز تلقی کردن دومین جاری برنامه است.


افزودن X-Xss-Protection
 context.Response.Headers.Add("X-Xss-Protection", "1; mode=block");
تقریبا تمام مرورگرهای امروزی قابلیت تشخیص حملات XSS را توسط static analysis توکار خود دارند. این هدر، آنالیز اجباری XSS را فعال کرده و همچنین تنظیم حالت آن به block، نمایش و رندر قسمت مشکل‌دار را به طور کامل غیرفعال می‌کند.


افزودن X-Content-Type-Options
 context.Response.Headers.Add("X-Content-Type-Options", "nosniff");
وجود این هدر سبب می‌شود تا مرورگر، حدس‌زدن نوع فایل‌ها، درخواست‌ها و محتوا را کنار گذاشته و صرفا به content-type ارسالی توسط سرور اکتفا کند. به این ترتیب برای مثال امکان لینک کردن یک فایل غیرجاوا اسکریپتی و اجرای آن به صورت کدهای جاوا اسکریپت، چون توسط تگ script ذکر شده‌است، غیرفعال می‌شود. در غیراینصورت مرورگر هرچیزی را که توسط تگ script به صفحه لینک شده باشد، صرف نظر از content-type واقعی آن، اجرا خواهد کرد.


افزودن Content-Security-Policy
string[] csp =
            {
              "default-src 'self'",
              "style-src 'self' 'unsafe-inline'",
              "script-src 'self' 'unsafe-inline' 'unsafe-eval'",
              "font-src 'self'",
              "img-src 'self' data:",
              "connect-src 'self'",
              "media-src 'self'",
              "object-src 'self'",
              "report-uri /api/CspReport/Log" //TODO: Add api/CspReport/Log
            };
context.Response.Headers.Add("Content-Security-Policy", string.Join("; ", csp));
وجود این هدر، تزریق کدها و منابع را از دومین‌های دیگر غیرممکن می‌کند. برای مثال ذکر self در اینجا به معنای مجاز بودن الصاق و اجرای اسکریپت‌ها، شیوه‌نامه‌ها، تصاویر و اشیاء، صرفا از طریق دومین جاری برنامه است و هرگونه منبعی که از دومین‌های دیگر به برنامه تزریق شود، قابلیت اجرایی و یا نمایشی نخواهد داشت.

در اینجا ذکر unsafe-inline و unsafe-eval را مشاهده می‌کنید. برنامه‌های Angular به همراه شیوه‌نامه‌های inline و یا بکارگیری متد eval در مواردی خاص هستند. اگر این دو گزینه ذکر و فعال نشوند، در کنسول developer مرورگر، خطای بلاک شدن آن‌ها را مشاهده کرده و همچنین برنامه از کار خواهد افتاد.

یک نکته: با فعالسازی گزینه‌ی aot-- در حین ساخت برنامه، می‌توان unsafe-eval را نیز حذف کرد.


استفاده از فایل web.config برای تعریف SameSite Cookies

یکی از پیشنهادهای اخیر ارائه شده‌ی جهت مقابله‌ی با حملات CSRF و XSRF، قابلیتی است به نام  Same-Site Cookies. به این ترتیب مرورگر، کوکی سایت جاری را به همراه یک درخواست ارسال آن به سایت دیگر، پیوست نمی‌کند (کاری که هم اکنون با درخواست‌های Cross-Site صورت می‌گیرد). برای رفع این مشکل، با این پیشنهاد امنیتی جدید، تنها کافی است SameSite، به انتهای کوکی اضافه شود:
 Set-Cookie: sess=abc123; path=/; SameSite

نگارش‌های بعدی ASP.NET Core، ویژگی SameSite را نیز به عنوان CookieOptions لحاظ کرده‌اند. همچنین یک سری از کوکی‌های خودکار تولیدی توسط آن مانند کوکی‌های anti-forgery به صورت خودکار با این ویژگی تولید می‌شوند.
اما مدیریت این مورد برای اعمال سراسری آن، با کدنویسی میسر نیست (مگر اینکه مانند نگارش‌های بعدی ASP.NET Core پشتیبانی توکاری از آن صورت گیرد). به همین جهت می‌توان از ماژول URL rewrite مربوط به IIS برای افزودن ویژگی SameSite به تمام کوکی‌های تولید شده‌ی توسط سایت، کمک گرفت. برای این منظور تنها کافی است فایل web.config را ویرایش کرده و موارد ذیل را به آن اضافه کنید:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <rewrite>
      <outboundRules>
        <clear />
        <!-- https://scotthelme.co.uk/csrf-is-dead/ -->
        <rule name="Add SameSite" preCondition="No SameSite">
          <match serverVariable="RESPONSE_Set_Cookie" pattern=".*" negate="false" />
          <action type="Rewrite" value="{R:0}; SameSite=lax" />
          <conditions></conditions>
        </rule>
        <preConditions>
          <preCondition name="No SameSite">
            <add input="{RESPONSE_Set_Cookie}" pattern="." />
            <add input="{RESPONSE_Set_Cookie}" pattern="; SameSite=lax" negate="true" />
          </preCondition>
        </preConditions>
      </outboundRules>
    </rewrite>
  </system.webServer>
</configuration>


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

اگر به هدر Content-Security-Policy دقت کنید، گزینه‌ی آخر آن، ذکر اکشن متدی در سمت سرور است:
   "report-uri /api/CspReport/Log" //TODO: Add api/CspReport/Log
با تنظیم این مورد، می‌توان موارد بلاک شده را در سمت سرور لاگ کرد. اما این اطلاعات ارسالی به سمت سرور، فرمت خاصی را دارند:
{
  "csp-report": {
    "document-uri": "http://localhost:5000/untypedSha",
    "referrer": "",
    "violated-directive": "script-src",
    "effective-directive": "script-src",
    "original-policy": "default-src 'self'; style-src 'self'; script-src 'self'; font-src 'self'; img-src 'self' data:; connect-src 'self'; media-src 'self'; object-src 'self'; report-uri /api/Home/CspReport",
    "disposition": "enforce",
    "blocked-uri": "eval",
    "line-number": 21,
    "column-number": 8,
    "source-file": "http://localhost:5000/scripts.bundle.js",
    "status-code": 200,
    "script-sample": ""
  }
}
به همین جهت ابتدا نیاز است توسط JsonProperty کتابخانه‌ی JSON.NET، معادل این خواص را تولید کرد:
    class CspPost
    {
        [JsonProperty("csp-report")]
        public CspReport CspReport { get; set; }
    }

    class CspReport
    {
        [JsonProperty("document-uri")]
        public string DocumentUri { get; set; }

        [JsonProperty("referrer")]
        public string Referrer { get; set; }

        [JsonProperty("violated-directive")]
        public string ViolatedDirective { get; set; }

        [JsonProperty("effective-directive")]
        public string EffectiveDirective { get; set; }

        [JsonProperty("original-policy")]
        public string OriginalPolicy { get; set; }

        [JsonProperty("disposition")]
        public string Disposition { get; set; }

        [JsonProperty("blocked-uri")]
        public string BlockedUri { get; set; }

        [JsonProperty("line-number")]
        public int LineNumber { get; set; }

        [JsonProperty("column-number")]
        public int ColumnNumber { get; set; }

        [JsonProperty("source-file")]
        public string SourceFile { get; set; }

        [JsonProperty("status-code")]
        public string StatusCode { get; set; }

        [JsonProperty("script-sample")]
        public string ScriptSample { get; set; }
    }
اکنون می‌توان بدنه‌ی درخواست را استخراج و سپس به این شیء ویژه نگاشت کرد:
namespace AngularTemplateDrivenFormsLab.Controllers
{
    [Route("api/[controller]")]
    public class CspReportController : Controller
    {
        [HttpPost("[action]")]
        [IgnoreAntiforgeryToken]
        public async Task<IActionResult> Log()
        {
            CspPost cspPost;
            using (var bodyReader = new StreamReader(this.HttpContext.Request.Body))
            {
                var body = await bodyReader.ReadToEndAsync().ConfigureAwait(false);
                this.HttpContext.Request.Body = new MemoryStream(Encoding.UTF8.GetBytes(body));
                cspPost = JsonConvert.DeserializeObject<CspPost>(body);
            }

            //TODO: log cspPost

            return Ok();
        }
    }
}
در اینجا نحوه‌ی استخراج Request.Body را به صورت خام را مشاهده می‌کنید. سپس توسط متد DeserializeObject کتابخانه‌ی JSON.NET، این رشته به شیء CspPost نگاشت شده‌است.


کدهای کامل این قسمت را از اینجا می‌توانید دریافت کنید.
پاسخ به بازخورد‌های پروژه‌ها
خطا هنگام اتصال
خوب مگر نباید همون پورتی باشه که برنامه ما روی اون داره کار می‌کنه ؟
الان وب اپلیکیشن من داره روی این پورت میاد بالا و طبیعتا پورت اشغال میشه و برنامه هم باید همین پورت رو listen کنه دیگه  !