تطوير الويب
29 دقيقة للقراءة

سلسلة كيفية العمل حول MVC وjQuery وJSON والصفحات وmapRoute

تقنيات تطوير تطبيقات ويب عالية الأداء باستخدام ASP.NET MVC وjQuery وJSON وحلول عملية.

ن
نجم الدين دمير
21 يوليو 2023
جاري التحميل...

سلسلة كيفية العمل حول MVC وjQuery وJSON والصفحات وmapRoute

MVC, jQuery, JSON, الصفحات
MVC, jQuery, JSON, الصفحات

تحميل الكود المصدري


المقدمة

بسبب الكمية الكبيرة من البيانات في أنظمة قواعد البيانات، أصبح العمل على جانب العميل مهمًا جدًا. في نهج code-behind مع ASP.NET الكلاسيكي، الطريقة الطبيعية هي كتابة معظم العمل في ملفات code-behind باستخدام مكونات ASP.NET. علاوة على ذلك، يُعتبر الآن عرض مكونات ASP.NET وآلية viewstate نقاط ضعف في ASP.NET الكلاسيكي.
لذلك ظهر نموذج جديد. وفقًا لهذا النموذج الجديد، يمكن للمطور العمل مع HTML نقي وJavaScript بدون viewstate الذي يخفض الأداء وبعرض أقل.
على الرغم من أن MVC معروف كنمط تصميم أو معماري قديم، إلا أنه أصبح شائعًا خاصة بعد اختناقات ASP.NET الكلاسيكي المذكورة أعلاه. في MVC حيث يُستخدم jQuery وJSON بفعالية، يمكن تطوير تطبيقات عالية الأداء.

المعرفة المسبقة

قد تكون هذه المقالة مفيدة بعد قراءة بعض المقالات التمهيدية حول MVC وjQuery وJSON. قد تكون الروابط التالية مفيدة للمبتدئين:

استخدام الكود

في هذه المقالة تم استهداف "سلسلة كيفية العمل". لذلك تم إعطاء جميع السكربتات من الكود المصدري المرفق. في الواقع، كل "كيفية العمل" يمكن أن تكون مقالة منفصلة. على أي حال، تم جمع جميع الإجابات الممكنة في مثال واحد. في هذه المقالة يوجد نهج عملي أكثر من المعلومات النظرية. مثلاً للبساطة تم استخدام بعض القوائم الثابتة بدلاً من قاعدة البيانات.
يتم الإجابة على الأسئلة التالية:
  1. كيف يتم عمل CRUD بأداء جيد في MVC؟
  2. كيف يُستخدم حوار jQuery بدلاً من confirm أو alert في JavaScript؟
  3. كيف يتم عمل الصفحات في قائمة MVC؟
  4. كيف يتم عمل رابط "عرض المزيد" في MVC باستخدام jQuery؟
  5. كيف تُستخدم الخاصية (attribute) مع الرابط؟
  6. كيف يتم استدعاء AJAX في jQuery؟
  7. كيف تُستخدم مجموعة Form في MVC؟
  8. كيف يتم حذف عدة سجلات دفعة واحدة؟
  9. كيف يُستخدم partial action في MVC؟
  10. كيف يُستخدم تنسيق JSON في تطبيق MVC؟
  11. كيف يتم ملء combobox رئيسي-تفصيلي؟
  12. كيف يُستخدم jQuery datepicker؟
  13. كيف يتم رفع صورة في MVC باستخدام حوار jQuery؟
  14. كيف يتم إنشاء صف جدول على جانب العميل؟
  15. كيف يتم تخصيص mapRoute في Global.asax؟
  16. كيف يتم تحديد الكل وإلغاء تحديد الكل لجميع صفوف الجدول؟
  17. كيف يتم عمل "جاري تحميل البيانات"؟
  18. كيف يتم عمل شبكات رئيسية-تفصيلية باستخدام jQuery؟

1) كيف يتم عمل CRUD بأداء جيد في MVC؟

بشكل تقريبي، جميع حلول الأعمال لديها ميزة Create-Read-Update-Delete (إنشاء-قراءة-تحديث-حذف). إذا أمكن، استخدام نفس "نموذج الحفظ" لكل من "الإدراج" و"التحديث" قد يكون فعالاً من حيث التكلفة للمطور. استخدام نفس النموذج ممكن بإدارة المعاملات المرسلة إلى الإجراء.
افترض أن لديك قائمة تشبه الشبكة (في الواقع جدول HTML) وزر "جديد" منفصل في النموذج. كل صف في الجدول له زر "تعديل" و"حذف" متعلقين بذلك الصف.
بعد النقر على "جديد"، إعادة التوجيه إلى صفحة جديدة - تسمى هنا view - ليست طريقة فعالة. لأنه بعد حفظ البيانات في الصفحة المعاد توجيهها، يحتاج المستخدم للنقر على "عرض القائمة" لرؤية البيانات المضافة إلى قاعدة البيانات. هذا يعني إعادة التوجيه إلى عرض القائمة وتحديد البيانات من قاعدة البيانات بتكلفة اختيار متغير!
بدلاً من سيناريو "انقر على جديد وأعد القائمة" المذكور أعلاه، يمكن تطبيق طريقة أفضل.
الإنشاء (Create):
  • في عرض القائمة، بعد النقر على "جديد"، يمكن أن يظهر "حوار حفظ jQuery".
  • يُعرض عرض الإنشاء في حوار jQuery.
  • يُملأ نموذج الإنشاء ويُضغط على "حفظ".
  • عند الضغط على زر الحفظ، يمكن إرسال البيانات إلى المتحكم المعني عبر AJAX post.
  • نموذج Ajax له دالة JavaScript onSuccess.
  • في طريقة JavaScript "onSuccess"، الصف الجديد المضاف، JSON القادم كمعامل لـ"onSuccess"، يُضاف إلى بداية القائمة (prepend) دون تحديث القائمة بأكملها.
القراءة (Read):
هذه عملية قائمة. إذا أمكن، يجب إظهار البيانات المطلوبة فقط في نموذج القائمة. يمكن استخدام التقنيات التالية:
  • الصفحات باستخدام combobox أو أرقام،
  • تنفيذ "عرض المزيد"،
  • القائمة مع التصفية.
التحديث (Update):
  • في عرض القائمة، بعد النقر على "تعديل" في أي صف من القائمة، يمكن أن يظهر نفس "حوار حفظ jQuery" ببيانات الصف المحدد.
  • بما أن جميع الخطوات مماثلة لـ"الإنشاء"، يتم تغيير طريقة "onSuccess" فقط حسب عملية "التحديث".
  • في هذه الحالة، بعد تحديث قاعدة البيانات، يتم تحديث البيانات في الصف المعدل فقط في العرض. بهذه الطريقة، لا حاجة لتحديث القائمة بأكملها لرؤية آخر سجل معدل.
الحذف (Delete):
  • بعد التأكيد بحوار jQuery ذو مظهر جميل، بعد حذف قاعدة البيانات، يتم إزالة الصف المحدد فقط من القائمة. مرة أخرى، لا حاجة لتحديث القائمة بأكملها.
يُستخدم نفس الحوار لكل من الإدراج والتعديل.
سجل جديد
سجل جديد
الروابط في عرض PersonList.cshtml كالتالي:
HTML
@Html.ActionLink("New", "Save", 
  new { personNo = 0 }, new { @class = "newLink" })
 
...
 
@Html.ActionLink("Edit", "Save", new { personNo = item.PersonNo }, new { @class = "editLink" })
  • New: النص المعروض.
  • Save: الإجراء في المتحكم.
  • personNo: المعامل المرسل إلى إجراء "Save". إذا كان 0، يُفتح الحوار فارغًا، إذا كان أكبر من 0 تُعرض بيانات ذلك المعرف في الحوار.
  • newLink: className وهمي سيُستخدم في jQuery التالي.
JavaScript
<div id="saveDialog" title="Person Information"></div>
 
<script type="text/javascript">
 
    var linkObj;
 
    //.....

    $(document).ready(function () {
 
       //...

        $('#saveDialog').dialog({
            autoOpen: false,
            width: 400,
            resizable: false,
            modal: true,
            buttons: {
                "Save": function () {
                    $("#update-message").html('');
                    $("#savePersonForm").submit();
                },
                "Cancel": function () {
                    $(this).dialog("close");
                }
            }
        });
 
 
       //....

       setLinks();
 
    });
 
    // ....
  
    function setLinks() 
    {
 
        $(".editLink, .newLink, uploadPicLink").unbind('click');

        $(".editLink, .newLink").click
        (
            function () 
            {
                linkObj = $(this);
                var dialogDiv = $('#saveDialog');
                var viewUrl = linkObj.attr('href');
                $.get(viewUrl, function (data) 
                {
                    dialogDiv.html(data);
                    //validation
                    var $form = $("#savePersonForm");
                    $form.unbind();
                    $form.data("validator", null);
                    $.validator.unobtrusive.parse(document);
                    $form.validate($form.data("unobtrusiveValidation").options);

                    dialogDiv.dialog('open');
                });

                return false;

            }
        );
 
        //...

 
    } //end setLinks
</script>
إجراء Save في PersonController كالتالي:
C#
// ...

[HttpGet]
public ActionResult Save(int personNo)
{
            
  Person person= new Person();
  person.BirthDate = DateTime.Today;
  person.PersonNo = 0;
            
  if (personNo > 0)
  {
     person = Repository.GetPersonList().Where(c => c.PersonNo == personNo).FirstOrDefault();
  }
 
  return PartialView(person);
 
}
 
 // ...  

[HttpPost]
public JsonResult Save(Person p)
{
     //...
}

// ...

2) كيف يُستخدم حوار jQuery بدلاً من confirm أو alert في JavaScript؟

صندوق الرسائل المخصص ممكن في تطبيقات Windows. للويب يكون ممكنًا عند استخدام مكتبة مكونات طرف ثالث. من الممكن أيضًا استخدام حوار jQuery بدلاً من صناديق JavaScript التالية:
تأكيد الحذف
تأكيد الحذف
رابط Delete في عرض PersonList كالتالي:
HTML
@Html.ActionLink("Delete", "DeletePerson", new { personNo = 
item.PersonNo }, new { @class = "deleteLink", @pkNo = item.PersonNo })
كود HTML وjQuery كالتالي:
JavaScript
<div id="confirmDialog" title="Warning"></div>
 
<script type="text/javascript">
//..
 
 $(".deleteLink").live("click", function (e) {
        e.preventDefault();

        // ..
        
        $("#confirmDialog").html('<br/><br/>sure?');

        $("#confirmDialog").dialog({
            resizable: false,
            height: 200,
            width: 300,
            modal: true,
            buttons: {
                "Yes": function () {
                    // ..

                 }, // end of yes button
                "No": function () {
                    $(this).dialog("close");
                }
            } //end buttons
        }); //end modal 
    });     //end delete
 
//...  
</script>

3) كيف يتم عمل الصفحات في قائمة MVC؟

الصفحات هي أحد الأساليب الجيدة لقائمة البيانات وتقليل تكلفة نقل البيانات. يمكن تطبيق العديد من الطرق لعرض البيانات. في هذه "الكيفية" تم استخدام combobox للصفحات. ومع ذلك، إذا رغبت، الترقيم في أسفل الصفحة ممكن أيضًا. هذا يعتمد على التطبيق والمطور. يمكن تطوير الصفحات مع combobox كالتالي.
الصفحات
الصفحات
أولاً، يتم ترتيب المكان لبيانات الصفحات التعريفية كالتالي:
HTML
@model AddressBook_mvc3_jQuery.Models.Paginginfo

...
 
<div id="paginginfo">
<hr />
    <select id="PageSelect"></select>
    
    <span class="pagingPersonNo" style="visibility:hidden">@Model.id</span>
    <span class="pagingTotalCount" style="visibility:hidden">@Model.TotalCount</span>
    <span class="pagingPageSize" style="visibility:hidden">@Model.PageSize</span>
 
    <span class="pagingSummary">aaa</span>
 
<hr/>
</div>
 
<div id="content"></div>
 
...
عند تحميل الصفحة لأول مرة، يُملأ div بمعرف "paginginfo" وتُعرض الصفحة الأولى من السجلات باستخدام السكربتات التالية.
JavaScript
<script type="text/javascript">
 
//..

  function initializePaging()
  {
       var PersonNo = $("#paginginfo .pagingPersonNo").text();
       var TotalCount = $("#paginginfo .pagingTotalCount").text();
       var PageSize = $("#paginginfo .pagingPageSize").text();
       
       var PageSelect = $("#PageSelect");
 
       if (TotalCount==0)
       {
            PageSelect.html("");
            $("#paginginfo").hide();
       }
       else
       {
             PageSelect.html("");
 
             var num = Math.ceil(TotalCount/PageSize);
 
             for (var i = 1; i <= num; i++) 
             {             
                 if (i==1)
                    PageSelect.append($("<option selected></option>").val(i).text(i));
                else
                    PageSelect.append($("<option></option>").val(i).text(i));
             }
      }
        
      fillData(PersonNo, 1); 
 
  }
 
//.. 

 function fillData(parPersonNo, parPageNo) 
 { 
    if (parPageNo) 
    {
        $.ajax({
            type: "POST", 
            url: "@Url.Action("GetAddressList", "Address")",
            data: { personNo: parPersonNo, pageNo: parPageNo },
            cache: false,
            dataType: "json",
            success: function (data) 
            {                                  
                if (data.Html) 
                {                       
                    $("#content").html(data.Html);
                    
                    buttonizeALL();
                    setLinkAbilites();
                    
                    setPagingSummary(parPageNo);
                }
                else 
                {
                    alert('opps!'); 
                }
            },
            error: function(exp)        
            {
                     alert('Error address : ' + exp.responseText);
            }                
        }); //end ajax call
    } // if (parPageNo) 

  }//fillData

//...

</script>
كود الإجراء في المتحكم كالتالي. كما يُرى، يتم عرض قائمة النتائج جزئيًا باستخدام طريقة RenderPartialView وتوضع في كائن JSON.
C#
public class AddressController : Controller
{
  //..

  public JsonResult GetAddressList(int personNo, int pageNo)
  {
        
        int pageSize = 5; //it could be parameter
        int skipCnt = ((pageNo - 1) * pageSize);

        List<Address> list = (from x in Repository.GetAddressList() where x.PersonNo == 
          personNo orderby x.AddressNo descending select x).Skip(skipCnt).Take(pageSize).ToList();
       
        JsonResult jr = Json(new
        {
            Html = this.RenderPartialView("AddressList", list),
            Message = "OK"
        }, JsonRequestBehavior.AllowGet);

        return jr;
  }
  //..

}
عند تغيير selecteditem للـcombo بمعرف "PageSelect" يعمل سكربت jQuery التالي.
JavaScript
//..

    $("#PageSelect").change(function () 
    {
 
        var $this = $(this);
        var parPageNo = $this.val();
 
        var parPersonNo = $("#paginginfo .pagingPersonNo").text();
 
        fillData(parPersonNo,parPageNo);
                      
    });//PageSelect

//..

4) كيف يتم عمل رابط "عرض المزيد" في MVC باستخدام jQuery؟

تُستخدم هذه التقنية في العديد من مواقع الويب الشائعة. يجب تطبيقها في القوائم الكبيرة. يمكن تحقيق "عرض المزيد" كالتالي:
عرض المزيد
عرض المزيد
في عرض القائمة يوجد رابط لـ"المزيد".
HTML
//
 
<table id="NoteTable"></table>
 
<br />
<a href="#"  style="display:none"  id="more">more</a>
 
<div id="saveDialog" title="Notes Information"></div>
<div id="confirmDialog" title="Warning"></div>
 
//
عند النقر على "more" يعمل سكربت jQuery التالي.
JavaScript
//..

   //load more results
    $(function () 
    {
        $("#more").click(function (e) 
        {
            e.preventDefault();
                       
            var lastNoteNo = $("#NoteTable tr:last .noteNo").text();

            if (lastNoteNo) 
            {
                var PersonNo = $("#paginginfo .pagingPersonNo").text();
                fillData(PersonNo, lastNoteNo); 
            }
 
            //--- scroll to bottom of page ---
            var $target = $('html,body'); 
            $target.animate({scrollTop: $target.height()}, "slow");
            //--- /scroll to bottom of page ---

            return false;
        });
    });
 
//..

 
   function fillData(parPersonNo, parLastNoteNo) 
    {                 
        if (parPersonNo) 
        {
            $.ajax({
                type: "POST",                
                url: "@Url.Action("GetNoteList", "Note")",
                data: { personNo: parPersonNo,  lastNoteNo: parLastNoteNo} ,
                cache: false,
                dataType: "json",
                success: function (data) 
                {
                    if (data.Html) 
                    {
                        $("#NoteTable").append(data.Html);
                        
                        buttonizeALL();
                        setLinkAbilites();
                        
                        if (data.HasMore)
                            $("#more").show();
                        else                        
                            $("#more").hide();
                    }
                    else 
                    {
                        alert('opps!'); 
                    }
                },                
                error: function(exp)        
                {
                        alert('Error address : ' + exp.responseText);
                }                
            }); //end ajax call
        } // if 
    }//func

// ..
الإجراء التالي في المتحكم يُرجع نتيجة JSON.
C#
public class NoteController : Controller
{
   //...

    public JsonResult GetNoteList(int personNo,  int lastNoteNo)
    {
        int pageSize = 5; //it could be parameter
        bool hasMore = false;

        List<Note> list = null;

        if (lastNoteNo == 0)
        {            
            list = (from x in Repository.GetNoteList() where x.PersonNo == personNo 
              orderby x.NoteNo descending select x).Take(pageSize).ToList();
            hasMore = (from x in Repository.GetNoteList() where x.PersonNo == 
              personNo select x.NoteNo).Take(pageSize + 1).Count() - pageSize > 0;
        }
        else
        {
            list = (from x in Repository.GetNoteList() where x.NoteNo < lastNoteNo && 
              x.PersonNo == personNo orderby x.NoteNo descending select x).Take(pageSize).ToList();
            hasMore = (from x in Repository.GetNoteList() where x.NoteNo < lastNoteNo && 
              x.PersonNo == personNo select x.NoteNo).Take(pageSize + 1).Count() - pageSize > 0;
        }
        
        JsonResult jr = Json(new
        {
            Html = this.RenderPartialView("_NoteList", list),
            Message = "OK",
            HasMore = hasMore
        }, JsonRequestBehavior.AllowGet);

        return jr;
    }

  // ...
}

5) كيف تُستخدم الخاصية (attribute) مع الرابط؟

هذه قدرة جيدة للاستخدام خاصة للأزرار مثل تعديل، حذف، إظهار التفاصيل.
عند إنشاء القائمة، يُضاف المفتاح المعني كخاصية للرابط. في حدث النقر للرابط يُستخدم ذلك المفتاح ويتم العمل بسهولة.
مثلاً، افترض أن لديك رابط حذف في كل صف من القائمة. عند النقر على رابط الحذف في الصف، من الممكن استخدام المفتاح كمعامل لـ"إجراء الحذف" في المتحكم.
HTML
@Html.ActionLink("Delete", "DeletePerson", new { personNo = item.PersonNo }, 
  new { @class = "deleteLink", @pkNo = item.PersonNo })
عند فحص المصدر في العميل يُرى السطر التالي.
HTML
<a role="button" class="deleteLink ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" 
  href="/Person/DeletePerson/1" pkno="1"><span class="ui-button-text">Delete</span></a>
في سكربت jQuery تُستخدم الخصائص كالتالي. مثلاً pkno هو 1 ويُستخدم.
JavaScript
$(".deleteLink").live("click", function (e) 
{
      e.preventDefault();
      var pkNo = $(this).attr("pkNo");
      //..
});

6) كيف يتم استدعاء AJAX في jQuery؟

استدعاء AJAX قدرة جيدة جدًا لجعل التطبيق أسرع. في بعض التطبيقات التي تحتوي على كمية كبيرة من البيانات في قاعدة البيانات، يجب على المطور الانتباه لنقل كمية صغيرة من البيانات في خطين للبيانات. الخط الأول بين قاعدة البيانات والتطبيق، والثاني بين التطبيق ومتصفح العميل. لمثل هذه المتطلبات، استدعاء AJAX مفيد جدًا.
JavaScript
//..

  $.ajax({
            type: "POST",
            url: "/Person/DeletePerson", 
            data: { personNo: pkNo },
            cache: false,
            dataType: "json",
            success: function () 
            {
                       //.. 
            },
            error: function (jqXHR, exception) 
            {
                 alert('Uncaught Error.\n' + jqXHR.responseText);
            }
         }); //end ajax call

//..
يمكن أيضًا استخدام URL كالتالي.
JavaScript
//..

url: "@Url.Action("DeletePerson", "Person")",
 
// ..

7) كيف تُستخدم مجموعة Form في MVC؟

عند إرسال نموذج، يتم إرسال جميع عناصر النموذج كمجموعة إلى الإجراء المعني في المتحكم. يمكن استخدام كل زوج مفتاح-قيمة في المتحكم. افترض أن لديك نموذج حفظ كالتالي:
HTML
@model AddressBook_mvc3_jQuery.Models.Address
@{ViewBag.Title = "Address"; }
 
@using (Ajax.BeginForm("Save", "Address", new AjaxOptions
                            {
                                InsertionMode = InsertionMode.Replace,
                                HttpMethod = "POST",
                                OnSuccess = "saveSuccess"
                            }, new { @id = "saveForm" }))
{
    @Html.ValidationSummary(true)
    <input style="visibility:hidden" type="text" name="TBPersonNo" 
      id="idTBPersonNo" value="@Model.PersonNo"/>
    <input style="visibility:hidden" type="text" name="TBAddressNo" 
      id="idTBAddressNo" value="@Model.AddressNo"/>
    
    <br />        
    <fieldset>       
        <table>        
        <tr>
        <td>Address Type</td>
        <td>        
          <select name="CBAddressType" id="idCBAddressType" style="width:120px">
          </select>
        </td>
        </tr>
        <tr>
        <td>Country</td>
        <td>            
            <select name="CBcountry" id="idCBcountry" style="width:120px">
            </select>
        </td>
        </tr>
        <tr>
        <td>City</td>
        <td>            
            <select name="CBcity" id="idCBcity" style="width:120px">
            </select>
        </td>
        </tr>
        <tr>
        <td>AddressText</td>
        <td>        
        <textarea rows="4" cols="25" name="TBAddressText" 
          id="idTBAddressText">@Model.AddressText</textarea>            
        </td>
        </tr>
        </table>        
    </fieldset>
}
يمكن إرسال البيانات من العرض إلى الإجراء في المتحكم ككائن نموذج أو كـFormCollection كما هو موضح أدناه:
C#
//..
 
[HttpPost]
public JsonResult Save(FormCollection fc)
{
    object obj = null;

                
    Address addrTmp = new Address();
    addrTmp.AddressNo = Convert.ToInt32(fc["TBAddressNo"].ToString());
    addrTmp.AddressTypeNo = Convert.ToInt32(fc["CBAddressType"].ToString());
    addrTmp.AddressText = fc["TBAddressText"].ToString();
    addrTmp.CityNo = Convert.ToInt32(fc["CBcity"].ToString()); ;
    addrTmp.PersonNo = Convert.ToInt32(fc["TBPersonNo"].ToString()); 
    
    if (ModelState.IsValid)
    {
        if (addrTmp.AddressNo == 0)
        {
            //find last person 
            //if it is database system no need to this line. Probably the AddressNo would be autoincrement
            addrTmp.AddressNo = Data.Repository.GetAddressList().OrderBy(x => x.AddressNo).Last().AddressNo + 1;

            Data.Repository.GetAddressList().Add(addrTmp);
            

            obj = new { Success = true, 
                        Message = "Added successfully", 
                        Object = addrTmp, 
                        operationType = "INSERT", 
                        Html = this.RenderPartialView("_addressLine", addrTmp )
                      };
        }
        else
        {
            Address addr = Repository.GetAddressList().Where(c => c.AddressNo == addrTmp.AddressNo).FirstOrDefault();
            addr.AddressTypeNo = addrTmp.AddressTypeNo;
            addr.AddressText = addrTmp.AddressText;
            addr.CityNo = addrTmp.CityNo;
            addr.PersonNo = addrTmp.PersonNo;

            obj = new { Success = true, 
                        Message = "Updated successfully", 
                        Object = addr, 
                        operationType = "UPDATE",
                        Html = this.RenderPartialView("_addressLine",  addr )
                      };
        }                

    }
    else
    {
        obj = new { Success = false, Message = "Please check form" };
    }

    return Json(obj, JsonRequestBehavior.DenyGet);
}
 
//..

8) كيف يتم حذف عدة سجلات دفعة واحدة؟

في بعض الصفحات أحيانًا حذف العديد من السجلات دفعة واحدة يُسهل العمل. حذف عدة سجلات ممكن بجمع مفاتيح جميع السجلات المحددة. بعد إرسال جميع المفاتيح إلى المتحكم، يمكن إجراء الحذف كالتالي.
الحذف المتعدد
الحذف المتعدد
أولاً يتم النقر على زر "Delete Selected" بمعرف "deleteALL". بعد الضغط على Yes يمكن استخدام سكربت jQuery التالي. بالطبع يمكن تطوير سكربتات بديلة أيضًا.
JavaScript
//..

$("#deleteALL").live("click", function (e) 
{
    e.preventDefault();
    
    var len = $("#NoteTable tr").length;
    
    $("#confirmDialog").html('<br/><br/>deleting all selecteds.. sure?');

    $("#confirmDialog").dialog({
        resizable: false,
        height: 200,
        width: 300,
        modal: true,
        buttons: 
        {
            "Yes": function () 
            {
                $(this).dialog("close");
                
                    var strSelecteds = '';
                    var rows = $("#NoteTable tr");

                    for(var i=0; i< rows.length; i++)
                    {                               
                        var row = $(rows).eq(i);

                        var span = row.find('span#cboxSpan');
                        var cb = row.find('span#cboxSpan').find('input.cboxDELclass');
                        
                        var checked=(cb.is(':checked'));

                        var pkno =  cb.attr("pkno"); 

                        if (checked)
                        {
                            strSelecteds = strSelecteds + pkno + ',';
                        }
                    }//
                            
                    if (strSelecteds.length>0)
                    {
                        strSelecteds = strSelecteds.substring(0,strSelecteds.length-1);
                    }
                    
                    if (strSelecteds.length>0)
                    {
                        $.ajax({
                            type: "POST",
                            url: "/Note/DeleteALL",   
                            data: { noteNOs: strSelecteds },
                            cache: false,
                            dataType: "json",
                            success: function (data) 
                            {
                                var  strSelectedsArr = strSelecteds.split(',');
                                for (var i = 0; i < strSelectedsArr.length; i++) 
                                {
                                    var rowNo = '#row-' + strSelectedsArr[i];
                                    $(rowNo).remove();  
                                    //alert(strSelectedsArr[i]);

                                }//for
                                

                                $('#saveDialog').dialog('close');
                                $('#Message').html(data.Message);
                                $('#Message').delay(300).slideDown(300).delay(1000).slideUp(300);
                            },                          
                            error: function(jqXHR, exception) 
                            {
                                alert('Uncaught Error.\n' + jqXHR.responseText);
                            }

                        }); //end ajax call
                    }
                    else
                        alert('No row selected');

            }, // end of yes button
            "No": function () 
            {
                $(this).dialog("close");
            }
        } //end buttons
    }); //end modal 

});    //end deleteALL
 
//...
كما يُرى أعلاه، يتم حذف العديد من السجلات باستدعاء ajax إلى إجراء "DeleteALL" في متحكم "Note".

9) كيف يُستخدم Partial Action في MVC؟

في بعض الحالات، يُطلب مكون يجب استخدامه في العديد من النماذج. مثلاً، قد يُطلب "صندوق معلومات الشخص" في بعض النماذج المنفصلة كما هو موضح أدناه.
HTML Action
HTML Action
عرض _personinfo قد يكون كالتالي.
HTML
@model AddressBook_mvc3_jQuery.Models.Person
 
@{ ViewBag.Title = "_personinfo"; }
           
<fieldset>
    <legend>Person info</legend>
 
    <table>
<tr><td><b><span> @Model.FirstName @Model.LastName </span></b>(@String.Format("{0:dd.MM.yyyy}", 
  Model.BirthDate))</td><td>(@Model.CategoryName)</td></tr>
    </table>
 
</fieldset>
لاستخدام partial action في أي عرض، يمكن استخدام سطر الكود التالي.
HTML
//..
 
<h2>Address List</h2>
<div> 
    @Html.Action("_personinfo", "Common") 
</div> 
 
//..

10) كيف يُستخدم تنسيق JSON في تطبيق MVC؟

يمكن استخدام تنسيق JSON عند إرسال معامل إلى إجراء في المتحكم وعند الحصول على نتيجة من إجراء. كما هو موضح أدناه، إجراء DeleteNote في متحكم Note لديه معامل noteNo. هنا pkNo هو معامل يُستدعى بقيمة.
JavaScript
$(".deleteLink").live("click", function (e) 
{
    e.preventDefault();

    var pkNo = $(this).attr("pkNo");

    //..

    $.ajax({
             type: "POST",
             url: "/Note/DeleteNote",
             data: { noteNo: pkNo },
             cache: false,
             dataType: "json",
             success: function () 
             {
               $(rowNo).remove();
             },
             error: function(jqXHR, exception) 
             {
                alert('Uncaught Error.\n' + jqXHR.responseText);
             }
            }); //end ajax call

    //.. 

});    //end delete
الحصول على نتيجة JSON من إجراء في المتحكم ممكن. السكربت التالي يُرجع النتيجة ككائن json.
C#
//..
 
[HttpPost]
public JsonResult DeleteNote(int noteNo)
{

    string message = string.Empty;

    try
    {
        Note n = Data.Repository.GetNoteList().Where(c => c.NoteNo == noteNo).FirstOrDefault();

        if (n != null)
        {
            Data.Repository.GetNoteList().Remove(n);
            message = "Deleted";
        }
        else
        {
            message = "Note not found!";
        }

    }
    catch (Exception ex)
    {
        message = ex.Message;
    }

    return Json(new { Message = message }, JsonRequestBehavior.AllowGet);
}

 
//..

11) كيف يتم ملء combobox رئيسي-تفصيلي؟

بعض النماذج تتطلب ملء combobox عند تغيير آخر. مثلاً، لزوج بلد-مدينة، يمكن اعتبار البلد رئيسي والمدينة تفصيلي.
Combobox رئيسي-تفصيلي
Combobox رئيسي-تفصيلي
HTML في عرض "نموذج الحفظ" كالتالي.
HTML
@model AddressBook_mvc3_jQuery.Models.Address
@{ViewBag.Title = "Address"; }
 
@using (Ajax.BeginForm("Save", "Address", new AjaxOptions
                            {
                                InsertionMode = InsertionMode.Replace,
                                HttpMethod = "POST",
                                OnSuccess = "saveSuccess"
                            }, new { @id = "saveForm" }))
{
    @Html.ValidationSummary(true)
    <input style="visibility:hidden" type="text" name="TBPersonNo" 
      id="idTBPersonNo" value="@Model.PersonNo"/>
    <input style="visibility:hidden" type="text" name="TBAddressNo" 
      id="idTBAddressNo" value="@Model.AddressNo"/>
    
    <br />        
    <fieldset>       
        <table>        
        <tr>
        <td>Address Type</td>
        <td>        
          <select name="CBAddressType" id="idCBAddressType" style="width:120px">
          </select>
        </td>
        </tr>
        <tr>
        <td>Country</td>
        <td>            
            <select name="CBcountry" id="idCBcountry" style="width:120px">  
            </select>
        </td>
        </tr>
        <tr>
        <td>City</td>
        <td>            
            <select name="CBcity" id="idCBcity" style="width:120px"> 
            </select>
        </td>
        </tr>
        <tr>
        <td>AddressText</td>
        <td>        
        <textarea rows="4" cols="25" name="TBAddressText" 
          id="idTBAddressText">@Model.AddressText</textarea>
        </td>
        </tr>
        </table>        
    </fieldset>
}
في التحميل الأول، يُملأ combobox بمعرف idCBCountry باستخدام إجراء "GetCountryList" في متحكم Address. بعد ذلك عند تغيير combobox البلد، يُملأ combobox المدينة كالتالي.
JavaScript
<script type="text/javascript">
 
    $(document).ready(function () {  
 
    //...
    //-----------------------------------------------------
    
                
   $.ajax({
        type: "POST",
        url: "@Url.Action("GetCountryList", "Address")",
        data: {},
        cache: false,
        dataType: "json",
        success: function (data) 
        {                               
             var idCBcountry = $("#idCBcountry");
             idCBcountry.html("");
                    
              if (@Model.AddressNo>0)
              {
                 for (var i = 0; i < data.List.length; i++) 
                 {
                    var item = data.List[i];

                    if (item.CountryNo == @Model.CountryNo)
                    {                                
                        idCBcountry.append($("<option selected></option>").val(item.CountryNo).text(item.CountryName));
                        fillCity(item.CountryNo);
                    }
                    else
                    {
                        idCBcountry.append($("<option />").val(item.CountryNo).text(item.CountryName));
                    }
                 }  //for   
              }      
              else
              {
                    for (var i = 0; i < data.List.length; i++) 
                     {
                        var item = data.List[i];
                        if (i==0)
                        {
                            idCBcountry.append($("<option selected></option>").val(item.CountryNo).text(item.CountryName));
                            fillCity(item.CountryNo);
                        }
                        else
                        {
                            idCBcountry.append($("<option />").val(item.CountryNo).text(item.CountryName));
                        }
                     }  //for
              }//else
            },  
            error: function(exp)        
            {
                 alert('ErrorCountry : ' + exp.responseText);
            }
        });
 
        //-----------------------------------------------------

            $("#idCBcountry").change(function () {
                var $this = $(this);
                var CountryNo = $this.val();
                if (CountryNo) 
                {
                    fillCity(CountryNo);

                }//if
            });

            //-----------------------------------------------------

});//end of function
 
function fillCity(parCountryNo)
{

    $.ajax({
        type: "POST",
        url: "@Url.Action("GetCityList", "Address")",
        data: {CountryNo: parCountryNo},
        cache: false,
        dataType: "json",
        success: function (data) 
        {
             var idCBcity = $("#idCBcity");
             idCBcity.html("");

             for (var i = 0; i < data.List.length; i++) 
             {
                var item = data.List[i];

                if (item.CityNo == @Model.CityNo)
                {
                    idCBcity.append($("<option selected></option>").val(item.CityNo).text(item.CityName));
                }
                else
                {
                    idCBcity.append($("<option />").val(item.CityNo).text(item.CityName));
                }
             }
        },
        error: function(exp)        
        {
             alert('ErrorCity : ' + exp.responseText);
        }
    });
}//fillCity

</script>
أكواد الإجراء كالتالي. تُضمّن القوائم في كائن json. بعد ذلك، في سكربت jQuery الموضح أعلاه، تُستخدم عناصر القائمة بالفهرس.
C#
public class AddressController : Controller
{
    //..

    public JsonResult GetCountryList()
    {
        object obj = null;
        List<Country> list = Repository.GetCountryList();
        obj = new { Success = true, Message = "OK", List = list };

        return Json(obj, JsonRequestBehavior.AllowGet);
    }
   
    public JsonResult GetCityList(int CountryNo)
    {
        object obj = null;

        List<City> list = Repository.GetCityList().Where(c => c.CountryNo == CountryNo).ToList(); ;
        obj = new { Success = true, Message = "OK", List = list };

        return Json(obj, JsonRequestBehavior.AllowGet);
    }

   //..
}
يمكن استخدام هذه التقنية لأي عنصر html في نموذج العرض.

12) كيف يُستخدم jQuery datepicker؟

يُستخدم نوع التاريخ في جميع تطبيقات الأعمال تقريبًا. بسبب اختلاف الثقافات، أحيانًا استخدام هذا النوع يعني مشكلة للمطور. لكن jQuery datepicker يُسهل استخدام نوع التاريخ.
jQuery Datepicker
jQuery Datepicker
لإظهار التاريخ بالتنسيق المطلوب في القائمة، يمكن استخدام السطر التالي.
HTML
<span class="BirthDate"> @String.Format("{0:dd.MM.yyyy}", item.BirthDate) </span>
في نموذج الحفظ يُستخدم سكربت HTML التالي.
HTML
  ...
       
    <div class="editor-label">
        @Html.LabelFor(model => model.BirthDate)
    </div>
    <div class="editor-field">         
        @Html.TextBoxFor(model => model.BirthDate, 
                new { @class = "BirthDateSave", 
                      @id = "TBBirthDate",
                      @Value = Model.BirthDate.ToString("dd.MM.yyyy") 
                    })
    </div>

   ...
jQuery Datepicker يمكن أن يعمل مع @Html.TextboxFor بالسكربت التالي في نفس الصفحة.
JavaScript
<script language="javascript" type="text/javascript">
 
 $(document).ready(function () {
    $(".BirthDateSave").datepicker({  
             changeMonth: true,
             changeYear: true,  
             dateFormat: 'dd.mm.yy',
             showOn: 'both'
                   });  
                });

</script>
يجب تضمين الأسطر التالية في بداية .cshtml المناسب.
HTML
..
  <link href="@Url.Content("~/Content/themes/base/jquery.ui.all.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-ui-1.8.11.min.js")" type="text/javascript"></script>
..

13) كيف يتم رفع صورة في MVC باستخدام حوار jQuery؟

يمكن رفع صورة بسهولة في عرض منفصل. لكن إعادة التوجيه إلى عرض منفصل فقط لرفع صورة ثم إعادة التوجيه إلى عرض القائمة قد يكون غير فعال من حيث التكلفة. بدلاً من ذلك، في عرض القائمة، بالنقر على رابط الرفع في كل صف، يمكن فتح حوار jQuery، تصفح صورة ورفعها.
رفع الصورة
رفع الصورة
عند النقر على "Upload Pic" يعمل السكربت التالي.
JavaScript
//..

$(".uploadPicLink").click
(
    function () 
    {

        linkObj = $(this);

        var dialogDiv = $('#savePicDialog');
        var viewUrl = linkObj.attr('href');
        $.get(viewUrl, function (data) {
            dialogDiv.html(data);
            //validation
            var $form = $("#savePersonPicForm");
            $form.unbind();
            $form.data("validator", null);
            $.validator.unobtrusive.parse(document);
            $form.validate($form.data("unobtrusiveValidation").options);

            dialogDiv.dialog('open');
        });

        return false;
    }
);

//..
نموذج SavePersonPic المحمل في حوار jQuery كالتالي. يُستخدم iframe لرفع الملف في حوار jQuery.
HTML
@model AddressBook_mvc3_jQuery.Models.Person            
@{ViewBag.Title = "Save image";}

@using (Html.BeginForm("SavePersonPic", "Person", FormMethod.Post,
             new
             {
                enctype = "multipart/form-data",        
                id = "savePersonPicForm",
                name = "savePersonPicForm",
                target = "UploadTarget"
              }))        
{
    @Html.ValidationSummary(true)    
    
    <div id="update-message" class="error invisible"></div>    
    <fieldset>
        <legend>Person Picture</legend> 
        <div class="editor-label">
            <label for="file">Upload Image:</label>
        </div>
        <div class="editor-field">
            <input type="file" name="file" id="file"/>        
        </div>      
 
    </fieldset>        
}

<iframe id="UploadTarget" 
   name="UploadTarget" onload="UploadImage_Complete();" 
        style="position: absolute; left: -999em; top: -999em;">
</iframe>
إجراء رفع الملف في المتحكم كالتالي:
C#
public class PersonController : Controller
{
    //..
    //-------------- image -----

    [HttpGet]
    public ActionResult SavePersonPic(int personNo)
    {

        Person person = new Person();
                    
        if (personNo > 0)
        {
            person = Repository.GetPersonList().Where(c => c.PersonNo == personNo).FirstOrDefault();
        }

        return PartialView(person);
    }
 
    [HttpPost]        
    public JsonResult SavePersonPic(HttpPostedFileBase file,   int personNo)
    {                
        string message = string.Empty;
        bool success = false;
        string imgPath = "";
        string fileName = "";
        try
        {
            string path = System.IO.Path.Combine(Server.MapPath("~/Content/images"), 
                            System.IO.Path.GetFileName(file.FileName));
            file.SaveAs(path);

            Person p = Data.Repository.GetPersonList().Where(r => r.PersonNo == personNo).FirstOrDefault();
            p.imgFileName = file.FileName;
            ViewBag.Message = "File uploaded successfully";
            message = ViewBag.Message;

            fileName = file.FileName;
            imgPath = Url.Content(String.Format("~/Content/images/{0}", fileName)); 
            
            success = true;

        }
        catch (Exception ex)
        {
            message = ex.Message;
            success = true;
            imgPath = "";
            fileName = "";
        }
 
        return Json(
                        new { Success = success, 
                              Message = message, 
                              PersonNo=personNo,
                              ImagePath = imgPath,
                              FileName = fileName
                            }, 
                        JsonRequestBehavior.AllowGet
                    );

    }

    //------------- /image --------
    // ..
}
دالة JavaScript "onload" للـiframe كالتالي. تُعرض الصورة المرفوعة في الصف المعني من القائمة دون تحديث الصف.
JavaScript
//..

function UploadImage_Complete() 
{            
    //Check first load of the iFrame
    if (isFirstLoad == true) 
    {
        isFirstLoad = false;
        return;
    }

    try 
    {            
        //Reset the image form
        document.getElementById("savePersonPicForm").reset();
    
        var jsonTxt = ($('#UploadTarget').contents()).text();            
        var jsonObj = JSON.parse(jsonTxt);
        
        var rowid = '#row-' + jsonObj.PersonNo;            
        var row = $('#personTable ' + rowid);           
        var imgid = "#img-" + jsonObj.PersonNo;
        var img = row.find(imgid);
            $(img).attr("src", jsonObj.ImagePath);

       
        $('#Message').html(jsonObj.Message);
        $('#Message').delay(300).slideDown(300).delay(1000).slideUp(300)


        $('#savePicDialog').dialog('close');
    }
    catch (err) 
    {
        alert(err.get_Message());
    }
}
 
//..

14) كيف يتم إنشاء صف جدول على جانب العميل؟

السجل المضاف إلى قاعدة البيانات يجب إظهاره في القائمة على جانب العميل. يمكن القيام بهذا بعدة طرق. بعد إضافة سجل، يمكن تحديث القائمة بالكامل من قاعدة البيانات لكن هذه عملية ثقيلة. ومع ذلك، باستخدام javascript أو jquery، يمكن إضافة صف جديد إلى العرض دون تحديث جميع العناصر في العرض. هنا يُذكر طريقتان.
الأولى، أدناه يتم إنشاء الصف وخلايا الصف واحدة تلو الأخرى بـjavascript. كما يُرى في السكربتات أدناه، دالة JavaScript saveSuccess تُستخدم لمثل هذا السيناريو بعد submit هذا النموذج.
HTML
..
 
@model AddressBook_mvc3_jQuery.Models.Person
            
@{  ViewBag.Title = "Save Person"; }
 
..
 
@using (Ajax.BeginForm("Save", "Person", new AjaxOptions
{
    InsertionMode = InsertionMode.Replace,
    HttpMethod = "POST",
    OnSuccess = "saveSuccess"    
}, new { @id = "savePersonForm" }))
{
    @Html.ValidationSummary(true)    
    
    ..        
}
 
..
طريقة javascript saveSuccess كالتالي. يُرجع الإجراء نتيجة json تحتوي على نوع العملية. حسب العملية، أي INSERT أو UPDATE، يتم تغيير الجدول في العرض. عند إضافة سجل جديد إلى قاعدة البيانات، يُضاف صف جديد إلى الجدول (prepend). عند تحديث سجل موجود في قاعدة البيانات، يتم تغيير الصف المعني فقط في الجدول.
JavaScript
function saveSuccess(data) 
{
    if (data.Success == true) 
    {
        if (data.operationType == 'UPDATE') 
        {
            //we update the table's row info
            var parent = linkObj.closest("tr");
            
            $(parent).animate({ opacity: 0.3 }, 200, function () 
            {;});

            parent.find(".FirstName").html(data.Object.FirstName);
            parent.find(".LastName").html(data.Object.LastName);
            parent.find(".CategoryName").html(data.Object.CategoryName);

            var date = new Date(parseInt(data.Object.BirthDate.substr(6)));
            var dateStr = FormatDate(date);                                     
            parent.find(".BirthDate").html(dateStr);


            $(parent).animate({ opacity: 1.0 }, 200, function () {
                ;
            });

        }
        else 
        {  //INSERT

            //we add the new row to table
            //we do not refresh all records on screen
            
            try 
            {                    
                var personTable = document.getElementById("personTable");
                var row = personTable.insertRow(1); //row 0 is header
                row.setAttribute("id", 'row-' + data.Object.PersonNo.toString());
                                                                 
                var buttonsLinks =
                '<a role="button" class="editLink ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only ui-state-hover ui-state-focus" href="/Person/Save/' + data.Object.PersonNo.toString() + '"><span class="ui-button-text">Edit</span></a> ' +
                '<a role="button" class="adressLink ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" href="/Address/Index/' + data.Object.PersonNo.toString()  + '"><span class="ui-button-text">Addresses</span></a> ' +
                '<a role="button" class="noteLink ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" href="/Note/Index/' + data.Object.PersonNo.toString() + '"><span class="ui-button-text">Notes</span></a> ' +
                '<a role="button" class="deleteLink ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" href="/Person/Delete/' + data.Object.PersonNo.toString() + '" pkno="' + data.Object.PersonNo.toString()  + '"><span class="ui-button-text">Delete</span></a>';

        
                var cellButtons = row.insertCell(0);
                cellButtons.innerHTML = buttonsLinks;

                var cellPersonNo = row.insertCell(1);
                cellPersonNo.innerHTML = "<span  class=\"PersonNo\">" + data.Object.PersonNo + "</span>";


                var cellCategoryName = row.insertCell(2);
                cellCategoryName.innerHTML = "<span  class=\"CategoryName\">" + data.Object.CategoryName + "</span>";

                var cellFN = row.insertCell(3);
                cellFN.innerHTML = "<span  class=\"FirstName\">" + data.Object.FirstName + "</span>";
                
                var cellLN= row.insertCell(4);
                cellLN.innerHTML = "<span  class=\"LastName\">" + data.Object.LastName + "</span>";

                var cellBirthDate = row.insertCell(5);
                var date = new Date(parseInt(data.Object.BirthDate.substr(6)));
                var dateStr = FormatDate(date);
                cellBirthDate.innerHTML = "<span  class=\"BirthDate\">" + dateStr + "</span>";

                var cellimgFileName = row.insertCell(6);
                cellimgFileName.innerHTML =
                    "<img id=\"img-" + data.Object.PersonNo.toString() + "\" alt=\"" + data.Object.ImgFileName + "\" src=\"/content/images/" + "noimg.jpg" + "\" height=\"35px\" width=\"50px\"><br><a class=\"uploadPicLink\" href=\"/Person/SavePersonPic/" + data.Object.PersonNo.toString() + "\" pkno=\"" + data.Object.PersonNo.toString() + "\" style=\"font-size:9px;\">Upload Pic</a>";

                
                setLinks();
                                 
            }
            catch (err) {
                alert(err.Message);
            }                               
        }
        
        $('#saveDialog').dialog('close');
        $('#Message').html(data.Message);
        $('#Message').delay(300).slideDown(300).delay(1000).slideUp(300);

    }
    else {
        $("#update-message").html(data.ErrorMessage);
        $("#update-message").show();
    }
}
الطريقة الأولى المذكورة أعلاه قد تبدو نهجًا قديمًا. لذلك، الطريقة الثانية التالية قد تكون أكثر قابلية للتطبيق. في هذه الطريقة، يُستخدم html المعروض لإضافة صف إلى الجدول أو تحديثه. افترض أن لديك جدول كالتالي.
HTML
@model IEnumerable<AddressBook_mvc3_jQuery.Models.Address>

<table id="AddressTable">
    <tr>
        <th></th>
        <th>
            #
        </th>       
        <th>
            AddressType
        </th>
        <th>
            City/Country
        </th>
        <th>
            Address Text
        </th>        
    </tr>
 
@foreach (var item in Model) 
{
    <tr id="row-@item.AddressNo">
        <td>            
            @Html.ActionLink("Edit", "Save", 
              new { addressNo = item.AddressNo, personNo = item.PersonNo }, new { @class = "editLink" })
            @Html.ActionLink("Delete", "DeleteAddress", 
              new { addressNo = item.AddressNo }, new { @class = "deleteLink", @pkNo = item.AddressNo })
        </td>
        <td>            
            <span class="AddressNo">@item.AddressNo</span>
        </td>       
        <td>            
            <span class="AddressTypeName">@item.AddressTypeName</span>
        </td>
        <td>            
            <span class="CityName">@item.CityName/@item.CountryName</span>
        </td>
        <td>            
            <span class="AddressText">@item.AddressText</span>
        </td>       
    </tr>
}
 
</table>
عند النقر على "new" يُحمل السكربت التالي في حوار jQuery.
HTML
@model AddressBook_mvc3_jQuery.Models.Address
@{ViewBag.Title = "Address"; }
 
@using (Ajax.BeginForm("Save", "Address", new AjaxOptions
                            {
                                InsertionMode = InsertionMode.Replace,
                                HttpMethod = "POST",
                                OnSuccess = "saveSuccess"
                            }, new { @id = "saveForm" }))
{
    @Html.ValidationSummary(true)
    <input style="visibility:hidden" type="text" 
      name="TBPersonNo" id="idTBPersonNo" value="@Model.PersonNo"/>
    <input style="visibility:hidden" type="text" 
      name="TBAddressNo" id="idTBAddressNo" value="@Model.AddressNo"/>
    
    <br />        
    <fieldset>       
        <table>        
        <tr>
        <td>Address Type</td>
        <td>        
          <select name="CBAddressType" id="idCBAddressType" style="width:120px">
          </select>
        </td>
        </tr>
        <tr>
        <td>Country</td>
        <td>            
            <select name="CBcountry" id="idCBcountry" style="width:120px">
            </select>
        </td>
        </tr>
        <tr>
        <td>City</td>
        <td>            
            <select name="CBcity" id="idCBcity" style="width:120px">
            </select>
        </td>
        </tr>
        <tr>
        <td>AddressText</td>
        <td>        
        <textarea rows="4" cols="25" name="TBAddressText" 
              id="idTBAddressText">@Model.AddressText</textarea>
        </td>
        </tr>
        </table>        
    </fieldset>
}
عند إرسال النموذج، يعمل الإجراء التالي في المتحكم.
C#
public class AddressController : Controller
{

    //..

    [HttpPost]
    public JsonResult Save(FormCollection fc)
    {
        object obj = null;

        Address addrTmp = new Address();
        addrTmp.AddressNo = Convert.ToInt32(fc["TBAddressNo"].ToString());
        addrTmp.AddressTypeNo = Convert.ToInt32(fc["CBAddressType"].ToString());
        addrTmp.AddressText = fc["TBAddressText"].ToString();
        addrTmp.CityNo = Convert.ToInt32(fc["CBcity"].ToString()); ;
        addrTmp.PersonNo = Convert.ToInt32(fc["TBPersonNo"].ToString()); 
        
        if (ModelState.IsValid)
        {
            if (addrTmp.AddressNo == 0)
            {
                //find last person 
                //if it is database system no need to this line. Probably the AddressNo would be autoincrement
                addrTmp.AddressNo = Data.Repository.GetAddressList().OrderBy(x => x.AddressNo).Last().AddressNo + 1;

                Data.Repository.GetAddressList().Add(addrTmp);

                obj = new { Success = true, 
                            Message = "Added successfully", 
                            Object = addrTmp, 
                            operationType = "INSERT", 
                                Html = this.RenderPartialView("_addressLine", addrTmp )
                          };
            }
            else
            {
                Address addr = Repository.GetAddressList().Where(c => c.AddressNo == addrTmp.AddressNo).FirstOrDefault();
                addr.AddressTypeNo = addrTmp.AddressTypeNo;
                addr.AddressText = addrTmp.AddressText;
                addr.CityNo = addrTmp.CityNo;
                addr.PersonNo = addrTmp.PersonNo;

                obj = new { Success = true, 
                            Message = "Updated successfully", 
                            Object = addr, 
                            operationType = "UPDATE", 
                                Html = this.RenderPartialView("_addressLine",  addr )
                          };
            }                

        }
        else
        {
            obj = new { Success = false, Message = "Please check form" };
        }

        return Json(obj, JsonRequestBehavior.DenyGet);
    }

    // .. 

}
تُستخدم طريقة RenderPartialView للحصول على سكربت html المطلوب.
C#
//..

public static string RenderPartialView(this Controller controller, string viewName, object model)
{
    if (string.IsNullOrEmpty(viewName))
        viewName = controller.ControllerContext.RouteData.GetRequiredString("action");

    controller.ViewData.Model = model;
    using (var sw = new StringWriter())
    {
        ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName);
        var viewContext = new ViewContext(controller.ControllerContext, 
               viewResult.View, controller.ViewData, controller.TempData, sw);
        viewResult.View.Render(viewContext, sw);

        return sw.GetStringBuilder().ToString();
    }
}

//..
دالة saveSuccess لـajax post في نموذج saveAddress كالتالي:
JavaScript
<script type="text/javascript">
 
    //...

    function saveSuccess(data) 
    {
        if (data.Success == true) 
        {            
            $("#paginginfo").show();       
 
            if (data.operationType == 'UPDATE') 
            {                           
                var row = linkObj.closest("tr");
                
                // the following line can also be used  to get related row
                //$('#AddressTable #row-' + data.Object.AddressNo); 

                row.replaceWith(data.Html);  
                //..
            }
            else 
            {  //INSERT

                try 
                {                                
                      $("#AddressTable tr:first").after(data.Html);
 
                     //..

                }
                catch (err) 
                {
                       alert(err.Message);
                }
            }
            
            //..

        }
        else 
        {
           //..
        }
    }
 
    //..
    
</script>
يمكن استخدام أي من التقنيتين الموضحتين أعلاه.

15) كيف يتم تخصيص mapRoute في Global.asax؟

في تطبيق asp.net الكلاسيكي، كانت عمليات urlRewrite تُنفذ بسهولة مع بعض assembly الطرف الثالث. في تطبيق MVC، من الممكن تخصيص mapRoutes باستخدام Global.asax.
mapRoute التالي هو الافتراضي في Global.asax:
C#
public class MvcApplication : System.Web.HttpApplication
{

    //..

    public static void RegisterRoutes(RouteCollection routes)
    {

       // all new customized maproute rules can be put here
        

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

    }

    //  .. 
}
حسب السكربت التالي يُستخدم **/Save/{addressNo}/{personNo}** كرابط.
HTML
@Html.ActionLink("Edit", "Save", 
  new { addressNo = item.AddressNo, personNo = item.PersonNo }, new { @class = "editLink" })
لقطة الشاشة للرابط أعلاه كالتالي.
MapRoute
MapRoute
لذلك، من الممكن إضافة قاعدة mapRoute مخصصة إلى Global.asax كالتالي.
C#
//..
 
routes.MapRoute(
    "AddressSave",
    "Address/Save/{addressNo}/{personNo}",
    new { controller = "Address", action = "Save", 
         addressNo = UrlParameter.Optional, personNo = UrlParameter.Optional }
);
 
//.. 
يمكن استخدام أي من التقنيتين الموضحتين أعلاه.

16) كيف يتم تحديد الكل وإلغاء تحديد الكل لجميع صفوف الجدول؟

في العديد من التطبيقات، قد يُطلب تحديد أو إلغاء تحديد جميع علامات الاختيار في جدول دفعة واحدة.
تحديد/إلغاء تحديد الكل
تحديد/إلغاء تحديد الكل
لمثل هذه الوظيفة يمكن استخدام السكربت التالي.
HTML
..

<br />
| <a href="#" class="checkALLRecords" id="checkALL">Check ALL</a> | <a href="#" class="unCheckALLRecords" id="unCheckALL">Uncheck ALL</a> |
<br />

..

<table id="NoteTable"></table>
..  
JavaScript
//..
 

        //check ALL records
        $("#checkALL").live("click", function (e) 
        {
                e.preventDefault();                                           
                CheckALL(true);
        });    
   
        //uncheck ALL records
        $("#unCheckALL").live("click", function (e) 
        {
                e.preventDefault();                                           
                CheckALL(false);
        });   


//..  

    function CheckALL(state)
    {
                            var rows = $("#NoteTable tr");
                                                       

                            for(var i=0; i< rows.length; i++)
                            {                               
                                var row = $(rows).eq(i);
                                                                                                                               
                                var span = row.find('span#cboxSpan');
                                var cb = row.find('span#cboxSpan').find('input.cboxDELclass');
                                
                                if (state==true)                                                                                                    
                                    cb.attr('checked',true);
                                else                                    
                                    cb.attr('checked',false);
                            }                           
    }



//..  

17) كيف يتم عمل "جاري تحميل البيانات"؟

عند تحميل عدة صفوف من البيانات، يجب إظهار رسالة "جاري تحميل البيانات" للمستخدمين.
جاري التحميل
جاري التحميل
يمكن تخصيص div التالي حسب الرسالة المطلوبة.
HTML
..
<div id="loadMessage"></div>
..   
يمكن استخدام دالة javascript التالية لتخصيص منطقة div.
JavaScript
..

function showLoader(root, txt) {
       
    $("#loadMessage").html("");
    $("#loadMessage").show();
    var loader = '<img src="' + root + '/ajax-loader.gif" align="absmiddle">&amp;nbsp;<span><br/>' + txt + '...</span>';
    $("#loadMessage").fadeIn(100).html(loader);
}

function hideLoader() {
    $("#loadMessage").hide();
}

..   

18) كيف يتم عمل شبكات رئيسية-تفصيلية باستخدام jQuery؟

عند النقر على الصف الرئيسي، تُعرض الصفوف التفصيلية أسفل الشبكة الرئيسية كما هو موضح أدناه.
شبكات رئيسية-تفصيلية
شبكات رئيسية-تفصيلية
تُستخدم الجداول التالية كشبكات.
HTML
..
<table id="CountryTable" class="hovertable2"></table>
<br />
<br />

<table id="CityTable" class="hovertable"></table>
..    
تُستخدم دوال javascript التالية لمحاكاة نهج الرئيسي-التفصيلي.
JavaScript
..

 function setTableRowClick()
   {        

        $("#CountryTable tr  td.clickable").unbind('click');
        
        $('#CountryTable  tr  td.clickable').click(function ()         
        {           
             var row = $(this).parent();             
             setRow(row);

        });

        //-------------        




   }//func 


   function setRow(row)
   {   
              var rowid = row.attr('id'); //current
                            
              var higlightedCountryTableRowid = $("#pageinfo .higlightedCountryTableRowid").text();               

               $("#pageinfo .higlightedCountryTableRowid").html(rowid.toString());

              if ((rowid==0) || (rowid!=higlightedCountryTableRowid))
              {
                  //------
                    row.siblings().removeClass('diffColor');                                              
                    row.addClass("diffColor");
                  //-------

                 fillCityData(rowid);
             }

   }


..   

    function fillCountryData() 
    {                         
            $.ajax({
                type: "POST",                
                url: "@Url.Action("GetCountryList", "Country")",
                data: {},
                cache: false,
                dataType: "json",
                success: function (data) 
                {                                  
                    if (data.Html) 
                    {                                        
                        $("#CountryTable").html(data.Html); 
                        
                        buttonizeALL();
                        
                        setLinkAbilitesCountry();  
                        setLinkAbilitesCity();

                                              
                        setTableRowClick();

                    }
                    else 
                    {
                        alert('opps-- country list error!'); 
                    }
                },                
                error: function(exp)        
                {
                         alert('Error address : ' + exp.responseText);
                }                
            }); //end ajax call
     

    }//func


    function fillCityData(parCountryNo) 
    {                         
            $.ajax({
                type: "POST",                
                url: "@Url.Action("GetCityList", "Country")",
                data: { countryNo: parCountryNo},                
                cache: false,
                dataType: "json",
                success: function (data) 
                {                                  
                    if (data.Html) 
                    {                                       
                        $("#CityTable").html(data.Html);        

                        
                        buttonizeALL();
                        setLinkAbilitesCity();                        
                        setTableRowClick();

                    }
                    else 
                    {
                        alert('opps-- city list error!'); 
                    }
                },                
                error: function(exp)        
                {
                         alert('Error address : ' + exp.responseText);
                }                
            }); //end ajax call
     

    }//func

.. 

الخلاصة

أتمنى أن تكون هذه المقالة مفيدة.

خدمات الحوسبة السحابية

نقدم خدمات تصميم البنية التحتية والترحيل والإدارة والتحسين على منصات AWS وAzure وGoogle Cloud.

استكشف خدماتنا

تواصل معنا

تحدث مع فريقنا للحصول على معلومات تفصيلية حول حلول AWS والحوسبة السحابية.

اتصل بنا