نظرات مطالب
ASP.NET MVC #11
خلاصه موردی را که عنوان کردید این است:
اگر یک صفحه داریم که از مثلا 4 ویجت نمایش آب و هوا، نمایش اخبار، نمایش تعداد کاربران حاضر در سایت و آمار سایت و نمایش منوی پویای سایت تشکیل شده، تمام این‌ها رو در یک ViewModel قرار ندیدم که اشتباه است. بله این مورد درست است؛ اما ... به معنای نفی استفاده از ViewModel ها نیست.
هر کدام از ویجت‌ها را می‌شود به Partial viewهای مختلفی برای مثال خرد کرد. اما نهایتا هر کدام از این اجزای کلی سیستم اصلی، نیاز به ViewModel دارند که این مورد، بحث اصلی جاری است. یعنی تفاوت قائل شدن بین domain model و view model. پوشه‌ی مدلی که در ساختار پروژه پیش فرض ASP.NET MVC قرار داره در واقع امر یک ViewModel است و نه مدل به معنای تعریف مدل‌های domain سیستم چون قرار است خواص آن مستقیما در View مورد استفاده قرار گیرند.
استفاده از ViewModelها کار را اندکی بیشتر می‌کنند، چون نهایتا خواص آن‌ها باید به مدل اصلی نگاشت شوند اما خوشبختانه برای این مورد هم راه حل هست و روش پیشنهادی، استفاده از کتابخانه‌ی سورس بازی است به نام AutpoMapper :  (^)
مطالب
پلاگین DataTables کتابخانه jQuery - قسمت چهارم
همان طور که قبلا اشاره کردیم، این پلاگین می‌تواند از یک زبان برنامه نویسی سمت سرور داده‌های مورد نیاز خودش را دریافت کند. می‌توانید داده‌ها را با استفاده از AJAX و به صورت JSON از سرور دریافت کرده و با استفاده از DataTables آنها را در جدول تزریق کنید. در این قسمت سعی خواهیم کرد تا با استفاده از jQuery DataTables یک گرید را در MVC ایجاد کنیم.  البته برای حذف جزئیات داده‌ها به جای این که از یک بانک اطلاعاتی دریافت شوند، در حافظه ساخته می‌شوند. در هر صورت اساس کار یکی است.

قصد داریم تا مانند مثال قسمت قبل، مجموعه ای از اطلاعات مربوط به مرورگرهای مختلف را در یک جدول نشان دهیم، اما این بار منبع داده ما فرق می‌کند. منبع داده از طرف سرور فراهم می‌شود. هر مرورگر - همان طور که در قسمت قبل مشاهده نمودید - شامل اطلاعات زیر خواهد بود:
  1. موتور رندرگیری (Engine)
  2. نام مرورگر (Name)
  3. پلتفرم (Platform)
  4. نسخه موتور (Version)
  5. نمره سی اس اس (Grade)

به همین دلیل در سمت سرور، کلاسی خواهیم ساخت که نمایانگر یک مرورگر باشد. بدین صورت:

public class Browser
{
    public int Id { get; set; }
    public string Engine { get; set; }
    public string Name { get; set; }
    public string Platform { get; set; }
    public float Version { get; set; }
    public string Grade { get; set; }
}

استفاده از روش server side processing برای دریافت داده‌ها از سرور

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

برای به کار گیری این روش، اولین کار این است که ویژگی bServerSide را true کنیم، مثلا بدین صورت:
var $table = $('#browsers-grid');
$table.dataTable({
      "bServerSide": true,
      "sAjaxSource": "/Home/GetBrowsers"
 });

همچنین ویژگی sAjaxSource را به Url ی که باید داده‌ها از آن دریافت شوند مقداردهی می‌کنیم.

به صورت پیش فرض مقدار ویژگی bServerSide مقدار false است؛ که یعنی منبع داده این پلاگین از سمت سرور خوانده نشود. اگر true باشد منبع داده و خیلی اطلاعات دیگر مربوط به داده‌های درون جدول باید از سرور به مرورگر کاربر پس فرستاده شوند. با true کردن مقدار bServerSide، آنگاه DataTables اطلاعاتی را راجع به شماره صفحه جاری، اندازه هر صفحه، شروط فیلتر کردن داده ها، مرتب سازی ستون ها، و غیره را به سرور می‌فرستد. همجنین انتظار می‌رود تا سرور در پاسخ به این درخواست، داده‌های مناسبی را به فرمت JSON به مرورگر پس بفرستد. در حالتی که bServerSide مقدار true به خود بگیرد، پلاگین فقط رابطه متقابل بین کاربر و سرور را مدیریت می‌کند و هیچ پردازشی را انجام نمی‌دهد.


در این درخواست XHR یا Ajax ی پارامترهایی که به سرور ارسال می‌شوند این‌ها هستند:

iDisplayStart عدد صحیح
نقظه شروع مجموعه داده جاری

iDisplayLength عدد صحیح
تعداد رکوردهایی که جدول می‌تواند نمایش دهد. تعداد رکوردهایی که از طرف سرور برگشت داده می‌شود باید با این عدد یکسان باشند.

iColumns عدد صحیح
تعداد ستونهایی که باید نمایش داده شوند.

sSearch رشته
فیلد جستجوی عمومی

bRegex بولین
اگر true باشد معنی آن این است که می‌توان از عبارات باقاعده برای جستجوی عبارتی خاص در کل ستون‌های جدول استفاده کرد. مثلا در کادر جستجو نوشت :

^[1-5]$
که یعنی 1 و 5 همه عددهای بین 1و 5.

bSearchable_(int)    بولین
نمایش می‌دهد که یک ستون در طرف کاربر قابلیت searchable آن true هست یا نه.

sSearch_(int)   رشته
فیلتر مخصوص هر ستون. اگر از ویژگی multi column filtering پلاگین استفاده شود به صورت sSearch0 ، sSearch1 ، sSeach2 و ... به طرف سرور ارسال می‌شوند. شماره انتهای هر کدام از پارامترها بیانگر شماره ستون جدول است.

bRegex_(int)  بولین
اگر true باشد، بیان می‌کند که می‌توان از عبارت با قاعده در ستون شماره int جهت جستجو استفاده کرد.

bSortable_(int) بولین
مشخص می‌کند که آیا یک ستون در سمت کلاینت، قابلیت مرتب شدن بر اساس آن وجود دارد یا نه. (در اینجا int اندیس ستون را مشخص می‌کند)

iSortingCols   عدد صحیح
تعداد ستون هایی که باید مرتب سازی بر اساس آنها صورت پذیرد. در صورتی که از امکان multi column sorting استفاده کنید این مقدار می‌تواند بیش از یکی باشد.

iSortCol_(int)   عدد صحیح
شماره ستونی که باید بر اساس آن عملیات مرتب سازی صورت پذیرد.

sSortDir_(int)    رشته
نحوه مرتب سازی ؛ شامل صعودی (asc) یا نزولی (desc)

mDataProp_(int)    رشته
اسم ستون‌های درون جدول را مشخص می‌کند.

sEcho     رشته
اطلاعاتی که datatables از آن برای رندر کردن جدول استفاده می‌کند.

شکل زیر نشان می‌دهد که چه پارامترهایی به سرور ارسال می‌شوند.



شکل ب ) پارامترهای ارسالی به سرور به صورت json

بعضی از این پارامترها بسته به تعداد ستون‌ها قابل تغییر هستند. (آن پارامترهایی که آخرشان یک عدد هست که نشان دهنده شماره ستون مورد نظر می‌باشد)

در پاسخ به هر درخواست XHR که datatables به سرور می‌فرستد، انتظار دارد تا سرور نیز یک شیء json را با فرمت مخصوص که شامل پارامترهای زیر می‌شود به او پس بفرستد:

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


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

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

sColumns    رشته
اسم ستون‌ها که با استفاده از کاما از هم جدا شده اند. استفاده از آن اختیاری است و البته منسوخ هم شده است و در نسخه‌های جدید jQuery DataTables از آن پشتیبانی نمی‌شود.

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

شکل زیر پارامترها دریافتی از سرور را نشان می‌دهند:


شکل ب ) پارامترهای دریافتی از سرور به صورت json

استفاده از روش server side processing در mvc
همان طور که گفتیم، کلاینت به سرور یک سری پارامترها را ارسال می‌کند و آن پارامترها را هم شرح دادیم. برای دریافت این پارامتر‌ها طرف سرور، احتیاج به یک مدل هست. این مدل به صورت زیر پیاده سازی خواهد شد:
/// <summary>
/// Class that encapsulates most common parameters sent by DataTables plugin
/// </summary>
public class jQueryDataTableParamModel
{
    /// <summary>
    /// Request sequence number sent by DataTable,
    /// same value must be returned in response
    /// </summary>
    public string sEcho { get; set; }
    /// <summary>
    /// Text used for filtering
    /// </summary>
    public string sSearch { get; set; }
    /// <summary>
    /// Number of records that should be shown in table
    /// </summary>
    public int iDisplayLength { get; set; }
    /// <summary>
    /// First record that should be shown(used for paging)
    /// </summary>
    public int iDisplayStart { get; set; }
    /// <summary>
    /// Number of columns in table
    /// </summary>
    public int iColumns { get; set; }
    /// <summary>
    /// Number of columns that are used in sorting
    /// /// </summary>
    public int iSortingCols { get; set; }
    /// <summary>
    /// Comma separated list of column names
    /// </summary>
    public string sColumns { get; set; }
}

مدل بایندر mvc وظیفه مقداردهی به خصوصیات درون این کلاس را بر عهده دارد، بقیه پارامترهایی که به سرور ارسال می‌شوند و در این کلاس نیامده اند، از طریق شیء Request در دسترس خواهند بود.


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

public JsonResult GetBrowsers(jQueryDataTableParamModel param)
{
        IQueryable<Browser> allBrowsers = new Browsers().CreateInMemoryDataSource().AsQueryable();

        IEnumerable<Browser> filteredBrowsers;

        // Apply Filtering
        if (!string.IsNullOrEmpty(param.sSearch))
        {
                filteredBrowsers = new Browsers().CreateInMemoryDataSource()
                    .Where(x => x.Engine.Contains(param.sSearch)
                                       || x.Grade.Contains(param.sSearch)
                                       || x.Name.Contains(param.sSearch)
                                       || x.Platform.Contains(param.sSearch)
                    ).ToList();
                float f;
                if (float.TryParse(param.sSearch, out f))
                {
                    filteredBrowsers = filteredBrowsers.Where(x => x.Version.Equals(f));
                }
        }
        else
        {
                filteredBrowsers = allBrowsers;
        }

        // Apply Sorting
        var sortColumnIndex = Convert.ToInt32(Request["iSortCol_0"]);
        Func<Browser, string> orderingFunction = (x => sortColumnIndex == 0 ? x.Engine :
                                                            sortColumnIndex == 1 ? x.Name :
                                                            sortColumnIndex == 2 ? x.Platform :
                                                            sortColumnIndex == 3 ? x.Version.ToString() :
                                                            sortColumnIndex == 4 ? x.Grade :
                                                                x.Name);

        var sortDirection = Request["sSortDir_0"]; // asc or desc
        filteredBrowsers = sortDirection == "asc" ? filteredBrowsers.OrderBy(orderingFunction) : filteredBrowsers.OrderByDescending(orderingFunction);

        // Apply Paging
        var enumerable = filteredBrowsers.ToArray();
        IEnumerable<Browser> displayedBrowsers = enumerable.Skip(param.iDisplayStart).
                Take(param.iDisplayLength).ToList();

        return Json(new
        {
                sEcho = param.sEcho,
                iTotalRecords = allBrowsers.Count(),
                iTotalDisplayRecords = enumerable.Count(),
                aaData = displayedBrowsers
        }, JsonRequestBehavior.AllowGet);
}

تشریح اکشن متد GetBrowsers :

این اکشن متد از مدل jQueryDataTableParamModel به عنوان پارامتر ورودی خود استفاده می‌کند. این مدل همان طور هم که گفتیم، شامل یک سری خصوصیت است که توسط پلاگین jQuery DataTables مقداردهی می‌شوند و همچنین مدل بایندر mvc وظیفه بایند کردن این مقادیر به خصوصیات درون این کلاس را بر عهده خواهد داشت. درون بدنه اکشن متد GetBrowsers داده‌ها بعد از اعمال عملیات فیلترینگ، مرتب سازی، و صفحه بندی به فرمت مناسبی درآمده و به طرف مرورگر فرستاده خواهند شد.

برای پیاده سازی کدهای طرف کلاینت نیز، درون یک View کدهای زیر قرار خواهند گرفت:
$(function () {
        var $table = $('#browsers-grid');
        $table.dataTable({
                "bProcessing": true,
                "bStateSave": true,
                "bServerSide": true,
                "bFilter": true,
                "sDom": 'T<"clear">lftipr',
                "aLengthMenu": [[5, 10, 25, 50, -1], [5, 10, 25, 50, "All"]],
                "bAutoWidth": false,
                "sAjaxSource": "/Home/GetBrowsers",
                "fnServerData": function (sSource, aoData, fnCallback) {
                    $.ajax({
                        "dataType": 'json',
                        "type": "POST",
                        "url": sSource,
                        "data": aoData,
                        "success": fnCallback
                    });
                },
                "aoColumns": [
                    { "mDataProp": "Engine" },
                    { "mDataProp": "Name" },
                    { "mDataProp": "Platform" },
                    { "mDataProp": "Version" },
                    { "mDataProp": "Grade" }
                ],
                "oLanguage": {
                        "sUrl": "/Content/dataTables.persian.txt"
                }
        });
});

تشریح کدها:

fnServerData :

این متد، در واقع نحوه تعامل سرور و کلاینت را با استفاده از درخواستهای XHR مشخص خواهد کرد.

oLanguage :

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

مثال این قسمت را از لینک زیر دریافت کنید:
DataTablesTutorial04.zip

لازم به ذکر است پوشه bin، obj، و packages جهت کاهش حجم این مثال از solution حذف شده اند. برای اجرای این مثال از اینجا کمک بگیرید.


مطالعه بیشتر

برای مطالعه بیشتر در مورد این پلاگین و نیز پیاده سازی آن در MVC می‌توانید به لینک زیر نیز مراجعه بفرمائید که بعضی از قسمتهای این مطلب هم از مقاله زیر استفاده کرده است:
jQuery DataTables and ASP.NET MVC Integration - Part I



نظرات مطالب
ارتقاء به ASP.NET Core 1.0 - قسمت 21 - بررسی تغییرات Bundling و Minification
پروژه‌ای که بر اساس دستور dotnet new mvc و به کمک SDK جدید ایجاد می‌شود (این دستور وابستگی به IDE شما ندارد)، فقط به همراه فایل‌های نهایی یکسری کتابخانه‌ی جاوا اسکریپتی و CSS ای است و راهی را برای مدیریت آن‌ها اضافه نکرده‌اند. بنابراین یا باید از روش مطلب جاری استفاده کنید (نمونه‌اش در اینجا) و یا از روش «LibMan».
نظرات مطالب
اجرای وظایف زمان بندی شده با Quartz.NET - قسمت اول
سلام.
ممنون بابت معرفی این کتابخانه‌ی مفید. جایی فرمودید که «در اینترفیس IJob در ASP.NET، به شی HttpContext دسترسی ندارید.» که درست نیست. شما در همه جای برنامه ASP.NET به کمک HttpContext.Current به HttpContext جاری دسترسی دارید. آیا استفاده از این روش مشکل خاصی داره؟
مطالب
پروژه Microsoft.AspNet.Mvc.Futures و تولید مسیرهای Strongly typed
پیشتر مطلبی را در مورد پروژه‌ی T4MVC در این سایت مطالعه کرد‌ه‌اید. هدف از آن تولید مسیرهای Strongly typed در ASP.NET MVC است. برای مثال بجای اینکه بنویسیم
 @Html.ActionLink("text", "Index", "Home")
می‌توان نوشت:
 @Html.ActionLink("text", result: MVC.Home.Index())
مزیت آن، امکان بررسی در زمان کامپایل مسیرهای تعریف شده‌است؛ بجای اینکه روزی متوجه شویم، مسیر تعریف شده‌ی قسمتی از پروژه، دیگر معتبر نیست و قسمت‌های متعددی تغییر کرده‌اند.
پروژه‌ی T4MVC توسط یکی از اعضای تیم ASP.NET تهیه شده‌است. همچنین مدتی است مایکروسافت پروژه‌ی دیگری را نیز به نام Microsoft.AspNet.Mvc.Futures در حال تهیه و آزمایش دارد که از آن نیز می‌توان برای تولید لینک‌های Strongly typed استفاده کرد.


نصب کتابخانه‌ی Microsoft ASP.NET MVC Futures

برای نصب کتابخانه‌ی آینده‌ی ASP.NET MVC، تنها کافی است دستور ذیل را در کنسول پاورشل نیوگت صادر کنید:
 PM> Install-Package Microsoft.AspNet.Mvc.Futures

نحوه‌ی تعریف مسیرهای Strongly typed، توسط کتابخانه‌ی آینده‌ی ASP.NET MVC

پس از نصب بسته‌ی Microsoft.AspNet.Mvc.Futures، جهت سهولت کار نیاز است اسمبلی آن‌را که Microsoft.Web.Mvc.dll نام دارد، به تمام صفحات سایت معرفی کنیم. برای این منظور فایل web.config پوشه‌ی views را گشوده و یک سطر تعریف فضای نام Microsoft.Web.Mvc را به آن اضافه کنید:
  <system.web.webPages.razor>
    <host  />
    <pages pageBaseType="System.Web.Mvc.WebViewPage">
      <namespaces>
        <!-- سایر تعاریف -->
        <add namespace="Microsoft.Web.Mvc"/> <!-- این سطر اضافه شود -->
      </namespaces>
    </pages>
  </system.web.webPages.razor>

یک نکته‌ی مهم
این بسته در حال حاضر هرچند دارای پوشه‌ی دات نت 4 است، اما عملا برای دات نت 4.5 یا به عبارتی ASP.NET MVC 5 کامپایل شده‌است و در ASP.NET MVC 4 قابل استفاده نیست:
 The primary reference "Microsoft.Web.Mvc" could not be resolved because it was built against the
".NETFramework,Version=v4.5" framework. This is a higher version than the currently targeted framework ".NETFramework,Version=v4.0"
 

ActionLink‌های جدید بسته‌ی Microsoft.AspNet.Mvc.Futures

به این ترتیب برای مثال در مورد ActionLink، دو overload جدید را می‌توان در Viewها استفاده کرد:
 public static System.Web.Mvc.MvcHtmlString ActionLink<TController>(this System.Web.Mvc.HtmlHelper helper,
System.Linq.Expressions.Expression<Action<TController>> action, string linkText)

public static System.Web.Mvc.MvcHtmlString ActionLink<TController>(this System.Web.Mvc.HtmlHelper helper,
System.Linq.Expressions.Expression<Action<TController>> action, string linkText, object htmlAttributes)
پارامتر دوم این متدهای الحاقی جدید که به صورت Expression Action تعریف شده‌اند، امکان تعریف مسیرهای Strongly typed را مهیا می‌کنند. برای مثال اینبار خواهیم داشت:
 @(Html.ActionLink<HomeController>(action => action.Index(id: 1), "Test"))
نحوه‌ی تعریف این متد الحاقی اندکی با متد Html.ActionLink اصلی متفاوت است. در اینجا باید کل عبارت داخل پرانتز قرارگیرد تا <>‌های تعریف آرگومان جنریک متد، به صورت تگ HTML تفسیر نشوند (مهم!).
همچنین اگر اکشن متد Index کنترلر HomeController دارای پارامتر نیز باشد، در همینجا قابل مقدار دهی است.


RenderAction و BeginForm‌های جدید بسته‌ی Microsoft.AspNet.Mvc.Futures

از این نوع متدهای الحاقی Expression Action دار، برای RenderAction و BeginForm نیز طراحی شده‌اند:
 public static void RenderAction<TController>(this System.Web.Mvc.HtmlHelper helper,
System.Linq.Expressions.Expression<Action<TController>> action)

public static System.Web.Mvc.Html.MvcForm BeginForm<TController>(this System.Web.Mvc.HtmlHelper helper,
System.Linq.Expressions.Expression<Action<TController>> action, System.Web.Mvc.FormMethod method,
System.Collections.Generic.IDictionary<string,object> htmlAttributes)
برای تعریف RenderAction جدید، ابتدا نوع کنترلر و سپس اکشن متد مرتبط با آن ذکر خواهد شد:
 @{ Html.RenderAction<HomeController>(action => action.Index(id: 1)); }
و نحوه‌ی استفاده از متد BeginForm جدید به نحو ذیل است:
 @using (Html.BeginForm<HomeController>(action => action.Index(null)))
{
}
در اینجا اگر متد Index دارای پارامتر باشد، فقط کافی است آن‌را null وارد کرد.


RedirectToAction جدید بسته‌ی Microsoft.AspNet.Mvc.Futures

به همراه دو متد کمکی Expression Action دار، جهت استفاده در متدهای کنترلرهای سایت؛ برای ساخت Url و همچنین redirect به یک اکشن متد دیگر:
 public static string BuildUrlFromExpression<TController>(System.Web.Routing.RequestContext context,
System.Web.Routing.RouteCollection routeCollection, System.Linq.Expressions.Expression<Action<TController>> action)

public static System.Web.Mvc.RedirectToRouteResult RedirectToAction<TController>(this System.Web.Mvc.Controller
controller, System.Linq.Expressions.Expression<Action<TController>> action)
برای مثال
using System.Web.Mvc;
using Microsoft.Web.Mvc;

namespace MVC5Basic.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            var link = LinkBuilder.BuildUrlFromExpression<HomeController>(
                            this.Request.RequestContext, null, action => action.About());

            this.RedirectToAction<HomeController>(action => action.About());
            return View();
        }

        public ActionResult About()
        {
            ViewBag.Message = "Your application description page.";

            return View();
        }
    }
}
ابتدا باید فضای نام Microsoft.Web.Mvc، جهت دسترسی به متدهای الحاقی جدید تعریف شود. در ادامه نحوه‌ی تولید یک رشته‌ی اشاره کننده به اکشن متدی خاص را مشاهده می‌کنید. همچنین RedirectToAction را نیز می‌توان بر اساس نام متدهای یک کنترلر مفروض بازنویسی کرد.


کدامیک بهتر است؟ T4MVC یا ASP.NET MVC Futures ؟
T4MVC موارد بیشتری را پوشش می‌دهد؛ حتی مسیرهای تصاویر ثابت و فایل‌های js را نیز می‌توان توسط آن تعریف کرد. فقط نگهداری آن هر بار نیاز به اجرای فایل t4 مرتبط با آن دارد و در اینجا کار با ASP.NET MVC Futures ساده‌تر است.


برای مطالعه بیشتر
بررسی که در اینجا صورت گرفت صرفا در مورد امکانات تولید مسیرهای strongly typed این کتابخانه است. سایر امکانات آن‌را در مطلب ذیل می‌توانید پیگیری کنید:
Using the Features of ASP.NET MVC 3 Futures  
پروژه‌ها
طراحی فریمورک برای کار با ASP.NET MVC و EF به صورت N-Layer

هدف اصلی بنده ساخت یک قالب  آماده بر اساس مقالاتی که تا الان در سایت جاری مطالعه کردم  و با امکان سطح دسترسی داینامیک، بود.همانطور که در مقاله مربوط به  چک لیست تهیه یک برنامه Asp.net MVC ، در نکات تکمیلی پیشنهاد شد:

" تهیه قالب‌های سفارشی VS.NET و لحاظ موارد فوق در آن جهت استفاده‌های بعدی نیز وجود دارد"


کاربر سیستمی
نام کاربری :SystemAdmin
کلمه عبور: Admin1234@gmail.com 

راه اندازی پروژه
از این مقاله کمک بگیرید و ورژن جدید را از مخزن پروژه دانلود کنید

موارد اضافه شده در ورژن آخر

  • بهبود سیستم فیلترینگ و مرتب سازی لیست کاربران
  • استفاده از  noty  به جای  toastr 
  • یکپارچه شده با Asp.net Web Api
  • یکپارچه شده با Asp.net SignalR