۱۳۹۱/۰۲/۰۵

ASP.NET MVC #21


آشنايي با تكنيك‌هاي Ajax در ASP.NET MVC

اهميت آشنايي با Ajax، ارائه تجربه‌ كاربري بهتري از برنامه‌هاي وب، به مصرف كنندگان نهايي آن مي‌باشد. به اين ترتيب مي‌توان درخواست‌هاي غيرهمزماني (asynchronous) را با فرمت XML يا Json به سرور ارسال كرد و سپس نتيجه نهايي را كه حجم آن نسبت به يك صفحه كامل بسيار كمتر است، به كاربر ارائه داد. غيرهمزمان بودن درخواست‌ها سبب مي‌شود تا ترد اصلي رابط كاربري برنامه قفل نشده و كاربر در اين بين مي‌تواند به ساير امور خود بپردازد. به اين ترتيب مي‌توان برنامه‌هاي وبي را كه شبيه به برنامه‌هاي دسكتاپ هستند توليد نمود؛ كل صفحه مرتبا به سرور ارسال نمي‌شود، flickering و چشمك زدن صفحه كاهش خواهد يافت (چون نيازي به ترسيم مجدد كل صفحه نخواهد بود و عموما قسمتي جزئي از يك صفحه به روز مي‌شود) يا بدون نياز به ارسال كل صفحه به سرور، به كاربري خواهيم گفت كه آيا اطلاعاتي كه وارد كرده است معتبر مي‌باشد يا نه (نمونه‌اي از آن‌ را در قسمت Remote validation اعتبار سنجي اطلاعات ملاحظه نموديد).


مروري بر محتويات پوشه Scripts يك پروژه جديد ASP.NET MVC در ويژوال استوديو

با ايجاد هر پروژه ASP.NET MVC‌ جديدي در ويژوال استوديو، يك سري اسكريپت‌ هم به صورت خودكار در پوشه Scripts آن اضافه مي‌شوند. تعدادي از اين فايل‌ها توسط مايكروسافت پياده سازي شده‌اند. براي مثال:
MicrosoftAjax.debug.js
MicrosoftAjax.js
MicrosoftMvcAjax.debug.js
MicrosoftMvcAjax.js
MicrosoftMvcValidation.debug.js
MicrosoftMvcValidation.js

اين فايل‌ها از ASP.NET MVC 3 به بعد، صرفا جهت سازگاري با نگارش‌هاي قبلي قرار دارند و استفاده از آن‌ها اختياري است. بنابراين با خيال راحت آن‌ها را delete كنيد! روش توصيه شده جهت پياده سازي ويژگي‌هاي Ajax ايي، استفاده از كتابخانه‌هاي مرتبط با jQuery مي‌باشد؛ از اين جهت كه 100ها افزونه براي كار با آن توسط گروه وسيعي از برنامه نويس‌ها در سراسر دنيا تاكنون تهيه شده است. به علاوه فريم ورك jQuery تنها منحصر به اعمال Ajax ايي نيست و از آن جهت دستكاري DOM (document object model) و CSS صفحه نيز مي‌توان استفاده كرد. همچنين حجم كمي نيز داشته،‌ با انواع و اقسام مرورگرها سازگار است و مرتبا هم به روز مي‌شود.

در اين پوشه سه فايل ديگر پايه كتابخانه jQuery نيز قرار دارند:
jquery-xyz-vsdoc.js
jquery-xyz.js
jquery-xyz.min.js

فايل vsdoc براي ارائه نهايي برنامه طراحي نشده است. هدف از آن ارائه Intellisense بهتري از jQuery در VS.NET مي‌باشد. فايلي كه بايد به كلاينت ارائه شود، فايل min يا فشرده شده آن است. اگر به آن نگاهي بيندازيم به نظر obfuscated مشاهده مي‌شود. علت آن هم حذف فواصل، توضيحات و همچنين كاهش طول متغيرها است تا اندازه فايل نهايي به حداقل خود كاهش پيدا كند. البته اين فايل از ديدگاه مفسر جاوا اسكريپت يك مرورگر، فايل بي‌نقصي است!
اگر علاقمند هستيد كه سورس اصلي jQuery را مطالعه كنيد، به فايل jquery-xyz.js مراجعه نمائيد.
محل الحاق اسكريپت‌هاي عمومي مورد نياز برنامه نيز بهتر است در فايل master page يا layout برنامه باشد كه به صورت پيش فرض اينكار انجام شده است.
ساير فايل‌هاي اسكريپتي كه در اين پوشه مشاهده مي‌شوند، يك سري افزونه عمومي يا نوشته شده توسط تيم ASP.NET MVC برفراز jQuery هستند.

به چهار نكته نيز حين استفاده از اسكريپت‌هاي موجود بايد دقت داشت:
الف) هميشه از متد Url.Content همانند تعاريفي كه در فايل Views\Shared\_Layout.cshtml مشاهده مي‌كنيد،‌ براي مشخص سازي مسير ريشه سايت، استفاده نمائيد. به اين ترتيب صرفنظر از آدرس جاري صفحه، همواره آدرس صحيح قرارگيري پوشه اسكريپت‌ها در صفحه ذكر خواهد شد.
ب) ترتيب فايل‌هاي js مهم هستند. ابتدا بايد كتابخانه اصلي jQuery ذكر شود و سپس افزونه‌هاي آن‌ها.
ج) اگر اسكريپت‌هاي jQuery در فايل layout سايت تعريف شده‌اند؛ نيازي به تعريف مجدد آن‌ها در View‌هاي سايت نيست.
د) اگر View ايي به اسكريپت ويژه‌اي جهت اجرا نياز دارد، بهتر است آن‌را به شكل يك section داخل view تعريف كرد و سپس به كمك متد RenderSection اين قسمت را در layout سايت مقدار دهي نمود. مثالي از آن‌را در قسمت 20 اين سري مشاهده نموديد (افزودن نمايش جمع هر ستون گزارش).


يك نكته
اگر آخرين به روز رساني‌هاي ASP.NET MVC را نيز نصب كرده باشيد، فايلي به نام packages.config به صورت پيش فرض به هر پروژه جديد ASP.NET MVC اضافه مي‌شود. به اين ترتيب VS.NET به كمك NuGet اين امكان را خواهد يافت تا شما را از آخرين به روز رساني‌هاي اين كتابخانه‌ها مطلع كند.


آشنايي با Ajax Helpers توكار ASP.NET MVC

اگر به تعاريف خواص و متدهاي كلاس WebViewPage دقت كنيم:

using System;

namespace System.Web.Mvc
{
    public abstract class WebViewPage<TModel> : WebViewPage
    {
        protected WebViewPage();
        public AjaxHelper<TModel> Ajax { get; set; }
        public HtmlHelper<TModel> Html { get; set; }
        public TModel Model { get; }
        public ViewDataDictionary<TModel> ViewData { get; set; }
        public override void InitHelpers();
        protected override void SetViewData(ViewDataDictionary viewData);
    }
}

علاوه بر خاصيت Html كه وهله‌اي از آن امكان دسترسي به Html helpers توكار ASP.NET MVC را در يك View فراهم مي‌كند، خاصيتي به نام Ajax نيز وجود دارد كه توسط آن مي‌توان به تعدادي متد AjaxHelper توكار دسترسي داشت. براي مثال توسط متد Ajax.ActionLink مي‌توان قسمتي از صفحه را به كمك ويژگي‌هاي Ajax، به روز رساني كرد.


مثالي در مورد به روز رساني قسمتي از صفحه به كمك متد Ajax.ActionLink

ابتدا نياز است فايل Views\Shared\_Layout.cshtml را اندكي ويرايش كرد. براي اين منظور سطر الحاق jquery.unobtrusive-ajax.min.js را به فايل layout برنامه اضافه نمائيد (اگر اين سطر اضافه نشود، متد Ajax.ActionLink همانند يك لينك معمولي رفتار خواهد كرد):

<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>
    <script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>    
</head>

سپس مدل ساده و منبع داده زير را نيز به پروژه اضافه كنيد:

namespace MvcApplication18.Models
{
    public class Employee
    {
        public int Id { set; get; }
        public string Name { set; get; }
    }
}

using System.Collections.Generic;

namespace MvcApplication18.Models
{
    public static class EmployeeDataSource
    {
        public static IList<Employee> CreateEmployees()
        {
            var list = new List<Employee>();
            for (int i = 0; i < 1000; i++)
            {
                list.Add(new Employee { Id = i + 1, Name = "name " + i });
            }
            return list;
        }
    }
}

در ادامه كنترلر جديدي را به برنامه با محتواي زير اضافه كنيد:

using System.Linq;
using System.Web.Mvc;
using MvcApplication18.Models;

namespace MvcApplication18.Controllers
{
    public class HomeController : Controller
    {
        [HttpGet]
        public ActionResult Index()
        {
            return View();
        }

        [HttpPost] //for IE-8        
        public ActionResult EmployeeInfo(int? id)
        {
            if (!Request.IsAjaxRequest())
                return View("Error");

            if (!id.HasValue)
                return View("Error");

            var list = EmployeeDataSource.CreateEmployees();
            var data = list.Where(x => x.Id == id.Value).FirstOrDefault();
            if (data == null)
                return View("Error");

            return PartialView(viewName: "_EmployeeInfo", model: data);
        }
    }
}

بر روي متد Index كليك راست كرده و گزينه Add view را انتخاب كنيد. يك View خالي را به آن اضافه نمائيد. همچنين بر روي متد EmployeeInfo كليك راست كرده و با انتخاب گزينه Add view در صفحه ظاهر شده يك partial view را اضافه نمائيد. جهت تمايز بين partial view و view هم بهتر است نام partial view با يك underline شروع شود.
كدهاي partial view مورد نظر را به نحو زير تغيير دهيد:

@model MvcApplication18.Models.Employee

<strong>Name:</strong> @Model.Name

سپس كدهاي View متناظر با متد Index را نيز به صورت زير اعمال كنيد:

@{
    ViewBag.Title = "Index";
}
<h2>
    Index</h2>

<div id="EmployeeInfo">
    @Ajax.ActionLink(
     linkText: "Get Employee-1 info",
     actionName: "EmployeeInfo",
     controllerName: "Home",
     routeValues: new { id = 1 },
     ajaxOptions: new AjaxOptions
                  {
                      HttpMethod = "POST",
                      InsertionMode = InsertionMode.Replace,
                      UpdateTargetId = "EmployeeInfo",
                      LoadingElementId = "Progress"
                  })
</div>

<div id="Progress" style="display: none">
    <img src="@Url.Content("~/Content/images/loading.gif")" alt="loading..."  />
</div>

توضيحات جزئيات كدهاي فوق

متد Ajax.ActionLink لينكي را توليد مي‌كند كه با كليك كاربر بر روي آن، اطلاعات اكشن متد واقع در كنترلري مشخص، به كمك ويژگي‌هاي jQuery Ajax دريافت شده و سپس در مقصدي كه توسط UpdateTargetId مشخص مي‌گردد، بر اساس مقدار InsertionMode،‌ درج خواهد شد (مي‌تواند قبل از آن درج شود يا پس از آن و يا اينكه كل محتواي مقصد را بازنويسي كند). HttpMethod آن هم به POST تنظيم شده تا با IE‌ مشكلي نباشد. از اين جهت كه IE پيغام‌هاي GET را كش مي‌كند و مساله ساز خواهد شد. توسط پارامتر routeValues، آرگومان مورد نظر به متد EmployeeInfo ارسال خواهد شد.
به علاوه يكي ديگر از خواص كلاس AjaxOptions، براي معرفي حالت بروز خطايي در سمت سرور به نام OnFailure در نظر گرفته شده است. در اينجا مي‌توان نام يك متد JavaScript ايي را مشخص كرده و پيغام خطاي عمومي را در صورت فراخواني آن به كاربر نمايش داد. يا توسط خاصيت Confirm آن مي‌توان يك پيغام را پيش از ارسال اطلاعات به سرور به كاربر نمايش داد.
به اين ترتيب در مثال فوق، id=1 به متد EmployeeInfo به صورت غيرهمزمان ارسال مي‌گردد. سپس كارمندي بر اين اساس يافت شده و در ادامه partial view مورد نظر بر اساس اطلاعات كاربر مذكور، رندر خواهد شد. نتيجه كار، در يك div با id مساوي EmployeeInfo درج مي‌گردد (InsertionMode.Replace). متد Ajax.ActionLink از اين جهت داخل div تعريف شده‌است كه پس از كليك كاربر و جايگزيني محتوا، محو شود. اگر نيازي به محو آن نبود، آن‌را خارج از div تعريف كنيد.
عمليات دريافت اطلاعات از سرور ممكن است مدتي طول بكشد (براي مثال دريافت اطلاعات از بانك اطلاعاتي). به همين جهت بهتر است در اين بين از تصاويري كه نمايش دهنده انجام عمليات است، استفاده شود. براي اين منظور يك div با id مساوي Progress تعريف شده و id آن به LoadingElementId انتساب داده شده است. اين div با توجه به display: none آن، در ابتداي امر به كاربر نمايش داده نخواهد شد؛ در آغاز كار دريافت اطلاعات از سرور توسط متد Ajax.ActionLink نمايان شده و پس از خاتمه كار مجددا مخفي خواهد شد.
به علاوه اگر به كدهاي فوق دقت كرده باشيد، از متد Request.IsAjaxRequest نيز استفاده شده است. به اين ترتيب مي‌توان تشخيص داد كه آيا درخواست رسيده از طرف jQuery Ajax صادر شده است يا خير. البته آنچنان روش قابل ملاحظه‌اي نيست؛ چون امكان دستكاري Http Headers هميشه وجود دارد؛ اما بررسي آن ضرري ندارد. البته اين نوع بررسي‌ها را در ASP.NET MVC بهتر است تبديل به يك فيلتر سفارشي نمود؛ به اين ترتيب حجم if و else نويسي در متدهاي كنترلرها به حداقل خواهد رسيد. براي مثال:

[AttributeUsage(AttributeTargets.Class|AttributeTargets.Method)]
public class AjaxOnlyAttribute : ActionFilterAttribute
{
  public override void OnActionExecuting(ActionExecutingContext filterContext)
  {
    if (filterContext.HttpContext.Request.IsAjaxRequest())
    {
      base.OnActionExecuting(filterContext);
    }
    else
    {
      throw new InvalidOperationException("This operation can only be accessed via Ajax requests");
    }
  }
}

و براي استفاده از آن خواهيم داشت:

[AjaxOnly]
public ActionResult SomeAjaxAction()
{
    return Content("Hello!");
}


در مورد كلمه unobtrusive در قسمت بررسي نحوه اعتبار سنجي اطلاعات، توضيحاتي را ملاحظه نموده‌ايد. در اينجا نيز از ويژگي‌هاي data-* براي معرفي پارامترهاي مورد نياز حين ارسال اطلاعات به سرور، استفاده مي‌گردد. براي مثال خروجي متد Ajax.ActionLink به شكل زير است. به اين ترتيب امكان حذف كدهاي جاوا اسكريپت از صفحه فراهم مي‌شود و توسط يك فايل jquery.unobtrusive-ajax.min.js كه توسط تيم ASP.NET MVC تهيه شده، اطلاعات مورد نياز به سرور ارسال خواهد گرديد:
<a data-ajax="true" data-ajax-loading="#Progress" data-ajax-method="POST" 
    data-ajax-mode="replace" data-ajax-update="#EmployeeInfo" 
    href="/Home/EmployeeInfo/1">Get Employee-1 info</a>

در كل اين روش قابليت نگهداري بهتري نسبت به روش اسكريپت نويسي مستقيم داخل صفحات را به همراه دارد. به علاوه جدا سازي افزونه اسكريپت وفق دهنده اين اطلاعات با متد jQuery.Ajax از صفحه جاري، كه امكان كش شدن آن‌را به سادگي ميسر مي‌سازد.


به روز رساني اطلاعات قسمتي از صفحه بدون استفاده از متد Ajax.ActionLink

الزامي به استفاده از متد Ajax.ActionLink و فايل jquery.unobtrusive-ajax.min.js وجود ندارد. اينكار را مستقيما به كمك jQuery نيز مي‌توان به نحو زير انجام داد:

<a href="#" onclick="LoadEmployeeInfo()">Get Employee-1 info</a>
@section javascript
{
    <script type="text/javascript">
        function LoadEmployeeInfo() {
            showProgress();
            $.ajax({
                type: "POST",
                url: "/Home/EmployeeInfo",
                data: JSON.stringify({ id: 1 }),
                contentType: "application/json; charset=utf-8",
                dataType: "json",
                // controller is returning a simple text, not json
                complete: function (xhr, status) {                    
                    var data = xhr.responseText;
                    if (status === 'error' || !data) {
                        //handleError                        
                    }
                    else {
                        $('#EmployeeInfo').html(data);
                    }
                    hideProgress();
                }
            });
        }
        function showProgress() {
            $('#Progress').css("display", "block");
        }
        function hideProgress() {
            $('#Progress').css("display", "none");
        }
    </script>
}

توضيحات:
توسط متد jQuery.Ajax نيز مي‌توان درخواست‌هاي Ajax ايي خود را به سرور ارسال كرد. در اينجا type نوع http verb مورد نظر را مشخص مي‌كند كه به POST تنظيم شده است. Url آدرس كنترلر را دريافت مي‌كند. البته حين استفاده از متد توكار Ajax.ActionLink،‌ اين لينك به صورت خودكار بر اساس تعاريف مسيريابي برنامه تنظيم مي‌شود. اما در صورت استفاده مستقيم از jQuery.Ajax بايد دقت داشت كه با تغيير تعاريف مسيريابي برنامه نياز است تا اين Url نيز به روز شود.
سه سطر بعدي نوع اطلاعاتي را كه بايد به سرور POST شوند مشخص مي‌كند. نوع json است و همچنين contentType آن براي ارسال اطلاعات يونيكد ضروري است. از متد JSON.stringify براي تبديل اشياء به رشته كمك گرفته‌ايم. اين متد در تمام مرورگرهاي امروزي به صورت توكار پشتيباني مي‌شود و استفاده از آن سبب خواهد شد تا اطلاعات به نحو صحيحي encode شده و به سرور ارسال شوند. بنابراين اين رشته ارسالي اطلاعات را به صورت دستي تهيه نكنيد؛ چون كاراكترهاي زيادي هستند كه ممكن است مشكل ساز شده و بايد پيش از ارسال به سرور اصطلاحا escape يا encode شوند.
متداول است از پارامتر success براي دريافت نتيجه عمليات متد jQuery.Ajax استفاده شود. اما در اينجا از پارامتر complete آن استفاده شده است. علت هم اينجا است كه return PartialView يك رشته را بر مي‌گرداند. پارامتر success انتظار دريافت خروجي از نوع json را دارد. به همين جهت در اين مثال خاص بايد از پارامتر complete استفاده كرد تا بتوان به رشته بدون فرمت خروجي بدون مشكل دسترسي پيدا كرد.
به علاوه چون از يك section براي تعريف اسكريپت‌هاي مورد نياز استفاده كرده‌ايم، براي درج خودكار آن در هدر صفحه بايد قسمت هدر فايل layout برنامه را به صورت زير مقدار دهي كرد:

@RenderSection("javascript", required: false)



دسترسي به اطلاعات يك مدل در View، به كمك jQuery Ajax

اگر جزئي از صفحه كه قرار است به روز شود، پيچيده است، روش استفاده از partial viewها توصيه مي‌شود؛ براي مثال مي‌توان اطلاعات يك مدل را به همراه يك گريد كامل از اطلاعات، رندر كرد و سپس در صفحه درج نمود. اما اگر تنها به اطلاعات چند خاصيت از مدلي نياز داشتيم، مي‌توان از روش‌هايي با سربار كمتر نيز استفاده كرد. براي مثال متد جديد زير را به كنترلر Home اضافه كنيد:

[HttpPost] //for IE-8        
public ActionResult EmployeeInfoData(int? id)
{
            if (!Request.IsAjaxRequest())
                return Json(false);

            if (!id.HasValue)
                return Json(false);

            var list = EmployeeDataSource.CreateEmployees();
            var data = list.Where(x => x.Id == id.Value).FirstOrDefault();
            if (data == null)
                return Json(false);

            return Json(data);
}

سپس View برنامه را نيز به نحو زير تغيير دهيد:

<a href="#" onclick="LoadEmployeeInfoData()">Get Employee-2 info</a>
@section javascript
{
    <script type="text/javascript">
        function LoadEmployeeInfoData() {
            showProgress();
            $.ajax({
                type: "POST",
                url: "/Home/EmployeeInfoData",
                data: JSON.stringify({ id: 1 }),
                contentType: "application/json; charset=utf-8",
                dataType: "json",
                // controller is returning the json data
                success: function (result) {
                    if (result) {
                        alert(result.Id + ' - ' + result.Name);
                    }
                    hideProgress();
                },
                error: function (result) {
                    alert(result.status + ' ' + result.statusText);
                    hideProgress();
                }
            });
        }

        function showProgress() {
            $('#Progress').css("display", "block");
        }
        function hideProgress() {
            $('#Progress').css("display", "none");
        }
    </script>
}

در اين مثال، كنترلر برنامه، اطلاعات مدل را تبديل به Json كرده و بازگشت خواهد داد. سپس مي‌توان به اطلاعات اين مدل و خواص آن در View برنامه، در پارامتر success متد jQuery.Ajax، مطابق كدهاي فوق دسترسي يافت. اينبار چون خروجي كنترلر تعريف شده از نوع Json است، امكان استفاده از پارامتر success فراهم شده است. همه چيز هم در اينجا خودكار است؛ تبديل يك شيء به Json و برعكس.
يك نكته: اگر نوع متد كنترلر، HttpGet باشد، نياز خواهد بود تا پارامتر دوم متد بازگشت Json، مساوي JsonRequestBehavior.AllowGet قرار داده شود.


ارسال اطلاعات فرم‌ها به سرور، به كمك ويژگي‌هاي Ajax

متد كمكي توكار ديگري به نام Ajax.BeginForm در ASP.NET MVC وجود دارد كه كار ارسال غيرهمزمان اطلاعات يك فرم را به سرور انجام داده و سپس اطلاعاتي را از سرور دريافت و قسمتي از صفحه را به روز خواهد كرد. مكانيزم كاري كلي آن بسيار شبيه به متد Ajax.ActionLink مي‌باشد. در ادامه با تكميل مثال قسمت جاري، به بررسي اين ويژگي خواهيم پرداخت.
ابتدا متد جستجوي زير را به كنترلر برنامه اضافه كنيد:

[HttpPost] //for IE-8        
public ActionResult SearchEmployeeInfo(string data)
{
            if (!Request.IsAjaxRequest())
                return Content(string.Empty);

            if (string.IsNullOrWhiteSpace(data))
                return Content(string.Empty);

            var employeesList = EmployeeDataSource.CreateEmployees();
            var list = employeesList.Where(x => x.Name.Contains(data)).ToList();
            if (list == null || !list.Any())
                return Content(string.Empty);

            return PartialView(viewName: "_SearchEmployeeInfo", model: list);
}

سپس بر روي نام متد كليك راست كرده و گزينه add view را انتخاب كنيد. در صفحه باز شده، گزينه create a stronlgly typed view را انتخاب كرده و قالب scaffolding را هم بر روي list قرار دهيد. سپس گزينه ايجاد partial view را نيز انتخاب كنيد. نام آن‌را هم _SearchEmployeeInfo وارد نمائيد. براي نمونه خروجي حاصل به نحو زير خواهد بود:

@model IEnumerable<MvcApplication18.Models.Employee>

<table>
    <tr>
        <th>
            Name
        </th>
    </tr>

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.Name)
        </td>
    </tr>
}

</table>

تا اينجا يك متد جستجو را ايجاد كرده‌ايم كه مي‌تواند ليستي از ركوردهاي كارمندان را بر اساس قسمتي از نام آن‌ها كه توسط كاربري جستجو شده است، بازگشت دهد. سپس اين اطلاعات را به partial view مورد نظر ارسال كرده و يك جدول را بر اساس آن توليد خواهيم نمود.
اكنون به فايل Index.cshtml مراجعه كرده و فرم Ajax ايي زير را اضافه نمائيد:

@using (Ajax.BeginForm(actionName: "SearchEmployeeInfo",
                       controllerName: "Home", 
                       ajaxOptions: new AjaxOptions
                                    {
                                         HttpMethod = "POST",
                                         InsertionMode = InsertionMode.Replace,
                                         UpdateTargetId = "EmployeeInfo",
                                         LoadingElementId = "Progress"
                                    }))
    {
      @Html.TextBox("data")
      <input type="submit" value="Search" />
    }

اينبار بجاي استفاده از متد Html.BeginForm از متد Ajax.BeginForm استفاده شده است. به كمك آن اطلاعات Html.TextBox تعريف شده، به كنترلر Home و متد SearchEmployeeInfo آن، بر اساس HttpMethod تعريف شده، ارسال گرديده و نتيجه آن در يك div با id مساوي EmployeeInfo درج مي‌گردد. همچنين اگر اطلاعاتي يافت نشد، به كمك متد return Content يك رشته خالي بازگشت داده مي‌شود.
متد Ajax.BeginForm نيز از ويژگي‌هاي data-* براي تعريف اطلاعات مورد نياز ارسالي به سرور استفاده مي‌كند. بنابراين نياز به سطر الحاق jquery.unobtrusive-ajax.min.js در فايل layout برنامه جهت وفق دادن اين اطلاعات unobtrusive به اطلاعات مورد نياز متد jQuery.Ajax وجود دارد.

<form action="/Home/SearchEmployeeInfo" data-ajax="true" 
          data-ajax-loading="#Progress" data-ajax-method="POST" 
          data-ajax-mode="replace" data-ajax-update="#EmployeeInfo" 
          id="form0" method="post">
       <input id="data" name="data" type="text" value="" />
       <input type="submit" value="Search" />
</form>


كتابخانه كمكي «ASP.net MVC Awesome - jQuery Ajax Helpers»
علاوه بر متدهاي توكار Ajax همراه با ASP.NET MVC، ساير علاقمندان نيز يك سري Ajax helper را بر اساس افزونه‌هاي jQuery تدارك ديده‌اند كه از آدرس زير قابل دريافت هستند:
http://awesome.codeplex.com/


افزودن فرم‌ها به كمك jQuery.Ajax و فعال سازي اعتبار سنجي سمت كلاينت

در ASP.NET MVC چون ViewState حذف شده است، امكان تزريق فرم‌هاي جديد به صفحه يا به روز رساني قسمتي از صفحه توسط jQuery Ajax به سهولت و بدون دريافت پيغام «viewstate is corrupted» در حين ارسال اطلاعات به سرور، ميسر است.
در اين حالت بايد به يك نكته مهم نيز دقت داشت: «اعتبار سنجي سمت كلاينت ديگر كار نمي‌كند». علت اينجا است كه در حين بارگذاري متداول يك صفحه، متد زير به صورت خودكار فراخواني مي‌گردد:
$.validator.unobtrusive.parse("#{form-id}");

اما با به روز رساني قسمتي از صفحه، ديگر اينچنين نخواهد بود و نياز است اين فراخواني را دستي انجام دهيم. براي مثال:

$.ajax
({
    url: "/{controller}/{action}/{id}",
    type: "get",
    success: function(data)
    {
        $.validator.unobtrusive.parse("#{form-id}");
    }
});

//or
$.get('/{controller}/{action}/{id}', function (data) { $.validator.unobtrusive.parse("#{form-id}"); });

شبيه به همين مساله را حين استفاده از Ajax.BeginForm نيز بايد مد نظر داشت:

@using (Ajax.BeginForm(
    "Action1",
    "Controller",
    null,
    new AjaxOptions { 
        OnSuccess = "onSuccess",
        UpdateTargetId = "result"
    },
    null)
)
{
    <input type="submit" value="Save" />
}

var onSuccess = function(result) {
    // enable unobtrusive validation for the contents
    // that was injected into the <div id="result"></div> node
    $.validator.unobtrusive.parse("#result");
};

در اين مثال در پارامتر UpdateTargetId، مجددا يك فرم رندر مي‌شود. بنابراين اعتبار سنجي سمت كلاينت آن ديگر كار نخواهد كرد مگر اينكه با مقدار دهي خاصيت OnSuccess، مجددا متد unobtrusive.parse را فراخواني كنيم.