مطالب
هدایت خودکار کاربر به صفحه لاگین در حین اعمال Ajax ایی
در ASP.NET MVC به کمک فیلتر Authorize می‌توان کاربران را در صورت درخواست دسترسی به کنترلر و یا اکشن متد خاصی در صورت لزوم و عدم اعتبارسنجی کامل، به صفحه لاگین هدایت کرد. این مساله در حین postback کامل به سرور به صورت خودکار رخ داده و کاربر به Login Url ذکر شده در web.config هدایت می‌شود. اما در مورد اعمال Ajax ایی چطور؟ در این حالت خاص، فیلتر Authorize قابلیت هدایت خودکار کاربران را به صفحه لاگین، ندارد. در ادامه نحوه رفع این نقیصه را بررسی خواهیم کرد.

تهیه فیلتر سفارشی SiteAuthorize

برای بررسی اعمال Ajaxایی، نیاز است فیلتر پیش فرض Authorize سفارشی شود:
using System;
using System.Net;
using System.Web.Mvc;

namespace MvcApplication28.Helpers
{
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
    public sealed class SiteAuthorizeAttribute : AuthorizeAttribute
    {
        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            if (filterContext.HttpContext.Request.IsAuthenticated)
            {
                throw new UnauthorizedAccessException(); //to avoid multiple redirects
            }
            else
            {
                handleAjaxRequest(filterContext);
                base.HandleUnauthorizedRequest(filterContext);
            }
        }

        private static void handleAjaxRequest(AuthorizationContext filterContext)
        {
            var ctx = filterContext.HttpContext;
            if (!ctx.Request.IsAjaxRequest())
                return;

            ctx.Response.StatusCode = (int)HttpStatusCode.Forbidden;
            ctx.Response.End();
        }
    }
}
در فیلتر فوق بررسی handleAjaxRequest اضافه شده است. در اینجا درخواست‌های اعتبار سنجی نشده از نوع Ajax ایی خاتمه داده شده و سپس StatusCode ممنوع (403) به کلاینت بازگشت داده می‌شود. در این حالت کلاینت تنها کافی است StatusCode یاده شده را مدیریت کند:
using System.Web.Mvc;
using MvcApplication28.Helpers;

namespace MvcApplication28.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }

        [SiteAuthorize]
        [HttpPost]        
        public ActionResult SaveData(string data)
        {
            if(string.IsNullOrWhiteSpace(data))
                return Content("NOk!");

            return Content("Ok!");
        }
    }
}
در کد فوق نحوه استفاده از فیلتر جدید SiteAuthorize را ملاحظه می‌کنید. View ارسال کننده اطلاعات به اکشن متد SaveData، در ادامه بررسی می‌شود:
@{
    ViewBag.Title = "Index";
    var postUrl = this.Url.Action(actionName: "SaveData", controllerName: "Home");
}
<h2>
    Index</h2>
@using (Html.BeginForm(actionName: "SaveData", controllerName: "Home",
                method: FormMethod.Post, htmlAttributes: new { id = "form1" }))
{
    @Html.TextBox(name: "data")
    <br />
    <span id="btnSave">Save Data</span>
}
@section Scripts
{
    <script type="text/javascript">
        $(document).ready(function () {
            $("#btnSave").click(function (event) {
                $.ajax({
                    type: "POST",
                    url: "@postUrl",
                    data: $("#form1").serialize(),
                    // controller is returning a simple text, not json  
                    complete: function (xhr, status) {
                        var data = xhr.responseText;
                        if (xhr.status == 403) {
                            window.location = "/login";
                        }
                    }
                });
            });
        });
    </script>
}
تنها نکته جدید کدهای فوق، بررسی xhr.status == 403 است. اگر فیلتر SiteAuthorize کد وضعیت 403 را بازگشت دهد، به کمک مقدار دهی window.location، مرورگر را وادار خواهیم کرد تا صفحه کنترلر login را نمایش دهد. این کد جاوا اسکریپتی، با تمام مرورگرها سازگار است.


نکته تکمیلی:
در متد handleAjaxRequest، می‌توان یک JavaScriptResult را نیز بازگشت داد تا همان کدهای مرتبط با window.location را به صورت خودکار به صفحه تزریق کند:
filterContext.Result =  new JavaScriptResult { Script="window.location = '" + redirectToUrl + "'"};
البته این روش بسته به نحوه استفاده از jQuery Ajax ممکن است نتایج دلخواهی را حاصل نکند. برای مثال اگر قسمتی از صفحه جاری را پس از دریافت نتایج Ajax ایی از سرور، تغییر می‌دهید، صفحه لاگین در همین قسمت در بین کدهای صفحه درج خواهد شد. اما روش یاد شده در مثال فوق در تمام حالت‌ها کار می‌کند.
مطالب
نگاهی به مزایا و معایب Xamarin.Android
حجم Package نهایی Xamarin.Android:
Xamarin هنگام ایجاد Package برنامه، روش‌های مختلفی را برای کاهش حجم آن به کار می‌برد که البته این روش‌ها همراه با حفظ کارآیی برنامه در حالت‌های Debug و Release می‌باشد.
یک برنامه‌ی Xamarin برای اجرا باید شامل: برنامه‌ی ما، کتابحانه‌های ارتباطی، محتویات، Mono runtime، اسمبلی‌های (BCL(Base Class Library باشد. برای مثال اگر شما همان مثال پیش فرض Hello work را که با ساخت Solution جدید ایجاد می‌شود، در نظر بگیرید، Package کامل آن بعد از ایجاد (build) به صورت زیر است:



واقعیت این هست که برای چنین برنامه‌ی کوچکی، 15مگابایت حجم زیادی به حساب می‌آید. بیشتر این حجم به دلیل کتابخانه‌ی کلاس‌های پایه (BCL) می‌باشد که شامل mscorlib.lib، system و Mono.Android هستند. این کلاس‌ها کامپوننت‌هایی را که برنامه‌ی ما برای اجرا به آن‌ها احتیاج دارند، فراهم می‌کنند. البته واقعیت این است که برنامه‌ی ما از تمام این امکانات استفاده نمی‌کند و می‌توان از خیلی از آن‌ها صرف نظر کرد.

وقتی شما برنامه‌ای را برای توزیع آماده می‌کنید، Xamarin پروسه‌ای را که به Linking معروف است، اجرا می‌کند. در این پروسه کدهایی که استفاده نشده‌اند حذف می‌شوند. به این ترتیب حجم کدهای برنامه را کاهش می‌دهند. در واقع بخش‌هایی از BCL را که استفاده نکرده‌ایم از Package نهایی حذف می‌کند. برای مثال پروژه‌ی "Hello Word"را در نظر بگیرید (پروژه‌ی پیش فرض). به دلیل آنکه ما از کلاس‌های خاصی استفاده نکرده‌ایم، مقدار زیادی از کدهای بلااستفاده‌ی BCL حذف می‌شوند. تصویر زیر حجم برنامه را مشخص می‌کند:



چه زمانی از Xamarin.Forms استفاده کنیم:

یکی از راه‌های ایجاد برنامه‌های بومی برای اندروید و iOS، استفاده از Xamarn.Android و Xamarin.iOS است. راه دیگر آن Xamarin.Forms است که بیشترین قابلیت اشتراک UI را دارا می‌باشد. در Xamarin.Forms ما می‌توانیم از XAML برای ایجاد UI استفاده کنیم. اما کی بهتر است از آن استفاده کنیم و چه وقت خوب نیست؟

مواردی که بهتر است از Xamarin.Forms استفاده کنیم:

  • برنامه‌های ورود اطلاعات (ِData Entry)
  • ایجاد نمونه‌های اولیه
  • برنامه‌هایی که به بازه‌ی وسیعی از قابلیت‌های بومی دستگاه مورد نظر احتیاج ندارد.
  • برنامه‌هایی که اشتراک کد برای ما مهمتر از نمای ظاهری و زیبایی برنامه باشد.


مواردی که بهتر است از Xamarin.Forms استفاده نکنیم

  • برنامه هایی که تعامل زیادی با کاربر دارد.
  • تهیه‌ی برنامه‌هایی با ظاهر بسیار زیبا و پر رنگ و لعاب!
  • برنامه‌هایی که نیاز به استفاده‌ی از بازه‌ی وسیعی از API‌های بومی را دارند.
  • برنامه هایی که در آن‌ها UIهای سفارشی مهم‌تر از اشتراک کد می‌باشند.
مطالب
ASP.NET MVC #14

آشنایی با نحوه معرفی تعاریف طرحبندی سایت به کمک Razor

ممکن است یک سری از اصطلاحات را در قسمت‌های قبل مانند master page در لابلای توضیحات ارائه شده، مشاهده کرده باشید. این نوع مفاهیم برای برنامه نویس‌های ASP.NET Web forms آشنا است (و اگر با Web forms view engine‌ در ASP.NET MVC کار کنید، دقیقا یکی است؛ البته با این تفاوت که فایل code behind آن‌ها حذف شده است). به همین جهت در این قسمت برای تکمیل بحث، مروری خواهیم داشت بر نحوه‌ی معرفی جدید آن‌ها توسط Razor.
در یک پروژه جدید ASP.NET MVC و در پوشه Views\Shared\_Layout.cshtml آن، فایل Layout آن،‌ مفهوم master page را دارد. در این نوع فایل‌ها، زیر ساخت مشترک تمام صفحات سایت قرار می‌گیرند:

<!DOCTYPE html>
<html>
<head>
<title>@ViewBag.Title</title>
<link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
<script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
</head>

<body>
@RenderBody()
</body>
</html>

اگر دقت کرده باشید، در هیچکدام از فایل‌های Viewایی که تا این قسمت به پروژه‌های مختلف اضافه کردیم، تگ‌هایی مانند body، title و امثال آن وجود نداشتند. در ASP.NET مرسوم است کلیه اطلاعات تکراری صفحات مختلف سایت را مانند تگ‌های یاد شده به همراه منویی که باید در تمام صفحات قرار گیرد یا footer‌ مشترک بین تمام صفحات سایت، به یک فایل اصلی به نام master page که در اینجا layout نام گرفته، Refactor کنند. به این ترتیب حجم کدها و markup تکراری که باید در تمام Viewهای سایت قرار گیرند به حداقل خواهد رسید.
برای مثال محل قرار گیری تعاریف Content-Type تمام صفحات و همچنین favicon سایت، بهتر است در فایل layout باشد و نه در تک تک Viewهای تعریف شده:

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="shortcut icon" href="@Url.Content("~/favicon.ico")" type="image/x-icon" />


در کدهای فوق یک نمونه پیش فرض فایل layout را مشاهده می‌کنید. در اینجا توسط متد RenderBody، محتوای رندر شده یک View درخواستی، به داخل تگ body تزریق خواهد شد.
تا اینجا در تمام مثال‌های قبلی این سری، فایل layout در Viewهای اضافه شده معرفی نشد. اما اگر برنامه را اجرا کنیم باز هم به نظر می‌رسد که فایل layout اعمال شده است. علت این است که در صورت عدم تعریف صریح layout در یک View، این تعریف از فایل Views\_ViewStart.cshtml دریافت می‌گردد:

@{
Layout = "~/Views/Shared/_Layout.cshtml";
}

فایل ViewStart، محل تعریف کدهای تکراری است که باید پیش از اجرای هر View مقدار دهی یا اجرا شوند. برای مثال در اینجا می‌شود بر اساس نوع مرورگر،‌ layout خاصی را به تمام Viewها اعمال کرد. مثلا یک layout‌ ویژه برای مرورگرهای موبایل‌ها و layout ایی دیگر برای مرورگرهای معمولی. امکان دسترسی به متغیرهای تعریف شده در یک View در فایل ViewStart از طریق ViewContext.ViewData میسر است.
ضمن اینکه باید درنظر داشت که می‌توان فایل ViewStart را در زیر پوشه‌های پوشه اصلی View نیز قرار داد. مثلا اگر فایل ViewStart ایی در پوشه Views/Home قرار گرفت، این فایل محتوای ViewStart اصلی قرار گرفته در ریشه پوشه Views را بازنویسی خواهد کرد.
برای معرفی صریح فایل layout، تنها کافی است مسیر کامل فایل layout را در یک View مشخص کنیم:

@{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Index</h2>

اهمیت این مساله هم در اینجا است که یک سایت می‌تواند چندین layout یا master page داشته باشد. برای نمونه یک layout برای صفحات ورود اطلاعات؛ یک layout خاص هم مثلا برای صفحات گزارش گیری نهایی سایت.
همانطور که پیشتر نیز ذکر شد، در ASP.NET حرف ~ به معنای ریشه سایت است که در اینجا ابتدای محل جستجوی فایل layout را مشخص می‌کند.
به این ترتیب زمانیکه یک کنترلر، View خاصی را فراخوانی می‌کند، کار از فایل Views\Shared\_Layout.cshtml شروع خواهد شد. سپس View درخواستی پردازش شده و محتوای نهایی آن، جایی که متد RenderBody قرار دارد، تزریق خواهد شد.
همچنین مقدار ViewBag.Title ایی که در فایل View تعریف شده، در فایل layout جهت رندر مقدار تگ title استفاده می‌شود (انتقال یک متغیر از View به یک فایل master page؛ کلاس layout، مدل View ایی را که قرار است رندر کند به ارث می‌برد).

یک نکته:
در نگارش سوم ASP.NET MVC امکان بکارگیری حرف ~ به صورت مستقیم در حین تعریف یک فایل js یا css وجود ندارد و حتما باید از متد سمت سرور Url.Content کمک گرفت. در نگارش چهارم ASP.NET MVC، این محدودیت برطرف شده و دقیقا همانند متغیر Layout ایی که در بالا مشاهده می‌کنید، می‌توان بدون نیاز به متد Url.Content، مستقیما از حرف ~ کمک گرفت و به صورت خودکار پردازش خواهد شد.


تزریق نواحی ویژه یک View در فایل layout

توسط متد RenderBody، کل محتوای View درخواستی در موقعیت تعریف شده آن در فایل Layout، رندر می‌شود. این ویژگی به نحو یکسانی به تمام Viewها اعمال می‌شود. اما اگر نیاز باشد تا view بتواند محتوای markup قسمت ویژه‌ای از master page را مقدار دهی کند، می‌توان از مفهومی به نام Sections استفاده کرد:
<!DOCTYPE html>
<html>
<head>
<title>@ViewBag.Title</title>
<link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
<script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
</head>
<body>
<div id="menu">
@if (IsSectionDefined("Menu"))
{
RenderSection("Menu", required: false);
}
else
{
<span>This is the default ...!</span>
}
</div>
<div id="body">
@RenderBody()
</div>
</body>
</html>

در اینجا ابتدا بررسی می‌شود که آیا قسمتی به نام Menu در View جاری که باید رندر شود وجود دارد یا خیر. اگر بله، توسط متد RenderSection، آن قسمت نمایش داده خواهد شد. در غیراینصورت، محتوای پیش فرضی را در صفحه قرار می‌دهد. البته اگر از متد RenderSection با آرگومان required: false استفاده شود، درصورتیکه View جاری حاوی قسمتی به نام مثلا menu نباشد، تنها چیزی نمایش داده نخواهد شد. اگر این آرگومان را حذف کنیم، یک استثنای عدم یافت شدن ناحیه یا قسمت مورد نظر صادر می‌گردد.
نحوه‌ی تعریف یک Section در Viewهای برنامه به شکل زیر است:
@{
ViewBag.Title = "Index";
//Layout = null;
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>
Index</h2>
@section Menu{
<ul>
<li>item 1</li>
<li>item 2</li>
</ul>
}

برای مثال فرض کنید که یکی از Viewهای شما نیاز به دو فایل اضافی جاوا اسکریپت برای اجرای صحیح خود دارد. می‌توان تعاریف الحاق این دو فایل را در قسمت header فایل layout قرار داد تا در تمام Viewها به صورت خودکار لحاظ شوند. یا اینکه یک section سفارشی را به نحو زیر در آن View خاص تعریف می‌کنیم:

@section JavaScript
{
<script type="text/javascript" src="@Url.Content("~/Scripts/SomeScript.js")" />;
<script type="text/javascript" src="@Url.Content("~/Scripts/AnotherScript.js")" />;
}

سپس کافی است جهت تزریق این کدها به header تعریف شده در master page مورد نظر، یک سطر زیر را اضافه کرد:

@RenderSection("JavaScript", required: false)

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



مدیریت بهتر فایل‌ها و پوشه‌های یک برنامه ASP.NET MVC به کمک Areas

به کمک قابلیتی به نام Areas می‌توان یک برنامه بزرگ را به چندین قسمت کوچکتر تقسیم کرد. هر کدام از این نواحی، دارای تعاریف مسیریابی، کنترلرها و Viewهای خاص خودشان هستند. به این ترتیب دیگر به یک برنامه‌ی از کنترل خارج شده ASP.NET MVC که دارای یک پوشه Views به همراه صدها زیر پوشه است، نخواهیم رسید و کنترل این نوع برنامه‌های بزرگ ساده‌تر خواهد شد.
برای مثال یک برنامه بزرگ را درنظر بگیرید که به کمک قابلیت Areas، به نواحی ویژه‌ای مانند گزارشگیری، قسمت ویژه مدیریتی، قسمت کاربران، ناحیه بلاگ سایت، ناحیه انجمن سایت و غیره، تقسیم شده است. به علاوه هر کدام از این نواحی نیز هنوز می‌توانند از اطلاعات ناحیه اصلی برنامه مانند master page آن استفاده کنند. البته باید درنظر داشت که فایل viewStart به پوشه جاری و زیر پوشه‌های آن اعمال می‌شود. اگر نیاز باشد تا اطلاعات این فایل به کل برنامه اعمال شود، فقط کافی است آن‌را به یک سطح بالاتر، یعنی ریشه سایت منتقل کرد.


نحوه افزودن نواحی جدید
افزودن یک Area جدید هم بسیار ساده است. بر روی نام پروژه در VS.NET کلیک راست کرده و سپس گزینه Add|Area را انتخاب کنید. سپس در صفحه باز شده، نام دلخواهی را وارد نمائید. مثلا نام Reporting را وارد نمائید تا ناحیه گزارشگیری برنامه از قسمت‌های دیگر آن مستقل شود. پس از افزودن یک Area جدید، به صورت خودکار پوشه جدیدی به نام Areas به ریشه سایت اضافه می‌شود. سپس داخل آن، پوشه‌ی دیگری به نام Reporting اضافه خواهد شد. پوشه reporting اضافه شده هم دارای پوشه‌های Model، Views و Controllers خاص خود می‌باشد.
اکنون که پوشه Areas به ریشه سایت اضافه شده است، با کلیک راست بر روی این پوشه نیز گزینه‌ی Add|Area در دسترس می‌باشد. برای نمونه یک ناحیه جدید دیگر را به نام Admin به سایت اضافه کنید تا بتوان امکانات مدیریتی سایت را از سایر قسمت‌های آن مستقل کرد.


نحوه معرفی تعاریف مسیریابی نواحی تعریف شده
پس از اینکه کار با Areas را آغاز کردیم، نیاز است تا با نحوه‌ی مسیریابی آن‌ها نیز آشنا شویم. برای این منظور فایل Global.asax.cs قرار گرفته در ریشه اصلی برنامه را باز کنید. در متد Application_Start، متدی به نام AreaRegistration.RegisterAllAreas، کار ثبت و معرفی تمام نواحی ثبت شده را به فریم ورک، به عهده دارد. کاری که در پشت صحنه انجام خواهد شد این است که به کمک Reflection تمام کلاس‌های مشتق شده از کلاس پایه AreaRegistration به صورت خودکار یافت شده و پردازش خواهند شد. این کلاس‌ها هم به صورت پیش فرض به نام SomeNameAreaRegistration.cs در ریشه اصلی هر Area توسط VS.NET تولید می‌شوند. برای نمونه فایل ReportingAreaRegistration.cs تولید شده، حاوی اطلاعات زیر است:

using System.Web.Mvc;

namespace MvcApplication11.Areas.Reporting
{
public class ReportingAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "Reporting";
}
}

public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Reporting_default",
"Reporting/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
}
}

توسط AreaName، یک نام منحصربفرد در اختیار فریم ورک قرار خواهد گرفت. همچنین از این نام برای ایجاد پیوند بین نواحی مختلف نیز استفاده می‌شود.
سپس در قسمت RegisterArea، یک مسیریابی ویژه خاص ناحیه جاری مشخص گردیده است. برای مثال تمام آدرس‌های ناحیه گزارشگیری سایت باید با http://localhost/reporting آغاز شوند تا مورد پردازش قرارگیرند. سایر مباحث آن هم مانند قبل است. برای مثال در اینجا نام اکشن متد پیش فرض، index تعریف شده و همچنین ذکر قسمت id نیز اختیاری است.
همانطور که ملاحظه می‌کنید، تعاریف مسیریابی و اطلاعات پیش فرض آن منطقی هستند و آنچنان نیازی به دستکاری و تغییر ندارند. البته اگر دقت کرده باشید مقدار نام controller پیش فرض، مشخص نشده است. بنابراین بد نیست که مثلا نام Home یا هر نام مورد نظر دیگری را به عنوان نام کنترلر پیش فرض در اینجا اضافه کرد.


تعاریف کنترلر‌های هم نام در نواحی مختلف
در ادامه مثال جاری که دو ناحیه Admin و Reporting به آن اضافه شده، به پوشه‌های Controllers هر کدام، یک کنترلر جدید را به نام HomeController اضافه کنید. همچنین این HomeController را در ناحیه اصلی و ریشه سایت نیز اضافه نمائید. سپس برای متد پیش فرض Index هر کدام هم یک View جدید را با کلیک راست بر روی نام متد و انتخاب گزینه Add view، اضافه کنید. اکنون برنامه را به همین نحو اجرا نمائید. اجرای برنامه با خطای زیر متوقف خواهد شد:

Multiple types were found that match the controller named 'Home'. This can happen if the route that services this
request ('{controller}/{action}/{id}') does not specify namespaces to search for a controller that matches the request.
If this is the case, register this route by calling an overload of the 'MapRoute' method that takes a 'namespaces' parameter.

The request for 'Home' has found the following matching controllers:
MvcApplication11.Areas.Admin.Controllers.HomeController
MvcApplication11.Controllers.HomeController

فوق العاده خطای کاملی است و راه حل را هم ارائه داده است! برای اینکه مشکل ابهام یافتن HomeController برطرف شود، باید این جستجو را به فضاهای نام هر قسمت از نواحی برنامه محدود کرد (چون به صورت پیش فرض فضای نامی برای آن مشخص نشده، کل ناحیه ریشه سایت و زیر مجموعه‌های آن‌را جستجو خواهد کرد). به همین جهت فایل Global.asax.cs را گشوده و متد RegisterRoutes آن‌را مثلا به نحو زیر اصلاح نمائید:

public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
, namespaces: new[] { "MvcApplication11.Controllers" }
);
}

آرگومان چهارم معرفی شده، آرایه‌ای از نام‌های فضاهای نام مورد نظر را جهت یافتن کنترلرهایی که باید توسط این مسیریابی یافت شوند، تعریف می‌کند.
اکنون اگر مجددا برنامه را اجرا کنیم، بدون مشکل View متناظر با متد Index کنترلر Home نمایش داده خواهد شد.
البته این مشکل با نواحی ویژه و غیر اصلی سایت وجود ندارد؛ چون جستجوی پیش فرض کنترلرها بر اساس ناحیه است.
در ادامه مسیر http://localhost/Admin/Home را نیز در مرورگر وارد کنید. سپس بر روی صفحه در مروگر کلیک راست کرده و سورس صفحه را بررسی کنید. مشاهده خواهید کرد که master page یا فایل layout ایی به آن اعمال نشده است. علت را هم در ابتدای بحث Areas مطالعه کردید. فایل Views\_ViewStart.cshtml در سطحی که قرار دارد به ناحیه Admin اعمال نمی‌شود. آن‌را به ریشه سایت منتقل کنید تا layout اصلی سایت نیز به این قسمت اعمال گردد. البته بدیهی است که هر ناحیه می‌تواند layout خاص خودش را داشته باشد یا حتی می‌توان با مقدار دهی خاصیت Layout نیز در هر view، فایل master page ویژه‌ای را انتخاب و معرفی کرد.


نحوه ایجاد پیوند بین نواحی مختلف سایت
زمانیکه پیوندی را به شکل زیر تعریف می‌کنیم:
@Html.ActionLink(linkText: "Home", actionName: "Index", controllerName: "Home")

یعنی ایجاد لینکی در ناحیه جاری. برای اینکه پیوند تعریف شده به ناحیه‌ای خارج از ناحیه جاری اشاره کند باید نام Area را صریحا ذکر کرد:

@Html.ActionLink(linkText: "Home", actionName: "Index", controllerName: "Home",
routeValues: new { Area = "Admin" } , htmlAttributes: null)


همین نکته را باید حین کار با متد RedirectToAction نیز درنظر داشت:
public ActionResult Index()
{
return RedirectToAction("Index", "Home", new { Area = "Admin" });
}


نظرات اشتراک‌ها
چرا از آنگولار به ری اکت + ری داکس سوئیچ کردم!
- فسلفه React مبتنی بر مخلوط کردن جاوا اسکریپت و HTML با هم هست در فایل‌های JSX (نوشتن HTML با کدهای جاوا اسکریپت). به این صورت شما مزیت‌های ذاتی HTML و CSS را یکجا از دست می‌دید؛ چون دیگه نمی‌تونید HTML جدا یا CSS جدای از جاوا اسکریپت را داشته باشین. در حالیکه در Angular این دو یا این سه (TypeScript، HTML و CSS) از هم جدا هستند که مزیت آن دسترسی به انواع ادیتورهایی هست که بدون اینکه برای Angular نوشته شده باشند، در همان بدو معرفی آن، با آن سازگار هستند که سادگی توسعه را به همراه داره. شاید تولید کامپوننت‌های ساده React تولید شده با کدهای جاوا اسکریپتی ساده باشه، اما کمی که حجم آن بیشتر شد، کنترل و مدیریت این مخلوط، سخت‌تر و سخت‌تر میشه و به علاوه مخلوط کردن کدهای یک فریم ورک با HTML و CSS خیلی شبیه به PHP کلاسیک و یا ASP کلاسیک هست و این روزها کسی را پیدا نمی‌کنید که برای پروژه‌های واقعی حتی از PHP در حالت کلاسیک آن بدون یک فریم ورک جانبی استفاده کنه. در Angular از همان بدو امر مباحث طراحی ماژول‌ها، کامپوننت‌ها و جدا سازی کدها به صورت ذاتی طراحی شده‌اند.
- مزیت کار کردن با TypeScript در مقایسه با ES6 خالص در React، امکان دسترسی به کامپایل آفلاین هست و مباحث پیشرفته‌ی کامپایلر مانند tree-shaking (حذف کدهای مرده) و AOT (a head of time compilation) که سبب می‌شن هم حجم نهایی کمتری تولید شود و هم پیش از اجرای برنامه در مرورگر و سپس یافتن باگ‌های احتمالی در زمان اجرا، پیش از موعد و توسط کامپایلر این باگ‌ها گزارش شوند. اگر قصد داشته باشید به یک چنین کیفیت و بررسی کدی در React برسید، باید تعداد آزمون‌های واحد قابل توجهی را داشته باشین تا بتونید یافتن مشکلاتی را که کامپایلر TypeScript گوشزد می‌کند، شبیه سازی کنید. همچنین شما در TypeScript می‌تونید به تمام امکانات پیشرفته‌ی زبان جاوا اسکریپت (حتی پس از ES6) دسترسی داشته باشید، اما کد نهایی جاوا اسکریپتی تولید شده‌ی توسط آن‌را برای ES5 که تمام مرورگرها از آن پشتیبانی می‌کنند، تولید کنید که این هم خودش یک مزیت مهم هست. بنابراین TypeScript فقط یک static type checker ساده نیست.
- اینکه Angular یک فریم‌ورک هست به خودی خودش یک مزیت مهم هست نسبت به React که یک کتابخانه است و اجزای آن باید از منابع مختلفی تهیه شوند. فریم ورک یعنی به روز رسانی‌های منظم تمام اجزای آن توسط خود تیم Angular و سازگاری کامل و یک‌دست هر جزء با نگارش فعلی یا همان آخرین نگارش موجود. اگر با دنیای وابستگی‌های ثالث در یک پروژه‌ی واقعی کار کرده باشید به خوبی می‌دونید که هر چقدر تعداد آن‌ها کمتر باشند، نگهداری طولانی مدت آن پروژه آسان‌تر می‌شود؛ چون روزی ممکن است آن کتابخانه‌ی ثالث دیگر توسعه پیدا نکند، یا منسوخ شود یا دیرتر از آخرین نگارش ارائه شده به روز رسانی شود. مزیت داشتن یک فریم ورک یک‌دست، درگیر نشدن با این مسایل است؛ خصوصا اینکه عموما کتابخانه‌های ثالث کیفیتشون در حد کتابخانه‌ی اصلی نیست و اینکه مثلا خود تیم Angular ماژول روتر، اعتبارسنجی یا فرم‌های اون رو توسعه می‌ده، قطعا کیفیتشون از کتابخانه‌های ثالث دیگه بهتر هست.
- در مورد سرعت و کارآیی و حتی مصرف حافظه، مطابق  یک benchmarck خیلی معتبر، وضعیت Angular اندکی بهتر از React است؛ هرچند در کل از این لحاظ به هم نزدیک هستند.
- این مباحث انحصاری شدن و این‌ها هم در مورد محصولات سورس باز، زیاد مفهومی ندارند و بیشتر یکسری شعار ایدئولوژیک هست توسط کسانیکه حتی تغییر رفتار این شرکت‌ها را هم دنبال نمی‌کنند و منابع و ماخذی رو که مطالعه کردن مربوط به یک دهه قبل هست. 
اشتراک‌ها
ابزار جدید گیت هاب (Copilot) برای نمایش کد پیشنهادی بر اساس هوش مصنوعی

گیت هاب از ابزار جدید هوش مصنوعی بنام copilot رونمایی کرده که از هوش مصنوعی استفاده می‌کند تا به شما در نوشتن کد با کارآیی بیشتر کمک کند. این ابزار می‌تواند خطوطی از کد و حتی بعضی اوقات کل توابع را به شما پیشنهاد دهد.  این ویژگی از طریق  Extentsion ای  در VS Code نیز قابل ارائه است

ابزار جدید گیت هاب (Copilot) برای نمایش کد پیشنهادی بر اساس هوش مصنوعی
اشتراک‌ها
انتخاب الگوریتم‌های هش سریع

این هش‌ها برای کارهای امن استفاده نمی‌شوند و صرفا کاربردهایی جهت تولید بانک‌های اطلاعاتی فوق سریع (key/value stores)، سیستم‌ها کش (تولید سریع کلید منحصربفرد) و یا جاهائیکه کارآیی بسیار مهم است، دارند. البته به نظر در حال حاضر xxHash از تمام این‌ها سریعتر است. یک نمونه پیاده سازی xxHash سریع در دات نت.

انتخاب الگوریتم‌های هش سریع
نظرات مطالب
مدیریت پیشرفته‌ی حالت در React با Redux و Mobx - قسمت دهم - MobX Hooks و اعمال Async در Mobx
کارآیی React+MobX بهتر است از React + Redux


همچنین اندازه‌ی نهایی React+MobX کمتر است از React + Redux


تعداد سطرهای مورد نیاز برای نوشتن یک برنامه‌ی مشابه توسط React+MobX، کمتر است از پیاده سازی همان برنامه با React+Redux

نظرات مطالب
چگونه نرم افزارهای تحت وب سریعتری داشته باشیم؟ قسمت سوم

هیچ کامپوننتی وجود خارجی نداره که قسمت مدیریت سمت بانک اطلاعاتی رو هم خودش به تنهایی انجام بده. همین کنترل‌های پیش فرض ASP.NET رو هم اگر ازشون درست استفاده کنیم، مشکلات کارآیی ندارند. مثلا: (نکته مهمش Skip.Take.ToList استفاده شده هست)

واکشی اطلاعات به صورت chunk chunk (تکه تکه) و نمایش در ListView

نظرات مطالب
EF Code First #12
- منطق تجاری مورد نظر رو باید به صورت یک متد با حد و مرز مشخص، کپسوله و داخل این متد از Skip و Take و سایر امکانات LINQ استفاده کنید.
- ضمنا نباید لیست تهیه کنید و بعد روی آن Take انجام دهید؛ چون کارآیی پایینی داره:
«تفاوت بین IQueryable و IEnumerable در حین کار با ORMs»
مطالب
درک نمودار

سؤال: از نمودار زیر چه چیزی را برداشت می‌کنید؟!



منحنی که بالا رفته یعنی چی؟ یعنی بده، خوبه؟!
منحنی‌های پایین‌تر یعنی چی؟ این‌ها بهترند یا بالایی‌های آن‌ها؟
با بالا رفتن حجم فایل‌ها، کدام یک کارآیی بهتری دارد؟ بالایی‌ها یا پایینی‌ها؟


ماخذ این نمودار:(+). البته قبل از مراجعه به ماخذ و مطالعه آن‌، سعی کنید به سؤالات فوق پاسخ دهید.