65.9K
CodeProject 正在变化。 阅读更多。
Home

"如何系列" 关于 MVC、jQuery、JSON、分页、mapRoute

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.91/5 (85投票s)

2013年3月24日

CPOL

12分钟阅读

viewsIcon

165035

downloadIcon

4813

"如何系列" 关于 MVC、jQuery、JSON、分页、mapRoute。

引言   

由于数据库系统中有大量数据,客户端工作变得非常重要。在传统的 ASP.NET 中,代码隐藏的自然方法是使用 ASP.NET 组件在代码隐藏文件中编写大部分工作。此外,ASP.NET 组件的渲染和视图状态机制现在被认为是经典 ASP.NET 的薄弱之处。

因此,出现了一种新的范例。根据这种新范例,开发人员可以处理纯 HTML 和 JavaScript,减少渲染并避免影响性能的视图状态。

尽管 MVC 被认为是一种古老的设计或架构模式,但它尤其在提到上述经典 ASP.NET 的瓶颈之后而变得流行。在 MVC 中有效利用 jQuery 和 JSON 可以开发出高性能的应用程序。

背景     

在阅读了一些关于 MVC、jQuery 和 JSON 的初级文章后,本文可能会有所帮助。以下链接可能对初学者有用:

使用代码 

本文旨在提供一个“如何系列”。因此,所有脚本都来自附加的源代码。事实上,每个“如何”都可以成为一篇独立的文章。无论如何,所有可能的答案都收集在一个示例中。本文中的实际方法多于理论知识。为了简化示例,使用了一些静态列表而不是数据库。

以下问题将得到解答:

  1. 如何在 MVC 中实现高性能的 CRUD 操作?
  2. 如何使用 jQuery 对话框代替 JavaScript 的 confirm 或 alert?
  3. 如何在 MVC 列表中实现分页? 
  4. 如何在 MVC 中使用“显示更多”链接?
  5. 如何在链接中使用属性?
  6. 如何在 jQuery 中进行 AJAX 调用?
  7. 如何在 MVC 中使用 Form collection?
  8. 如何一次删除多条记录?
  9. 如何在 MVC 中使用部分视图操作(partial action)?
  10. 如何在 MVC 应用程序中使用 JSON 格式?
  11. 如何填充主从组合框(master-detail combobox)?
  12. 如何使用 jQuery datepicker?
  13. 如何在 MVC 中使用 jQuery 对话框上传图片?
  14. 如何在客户端创建表格行?
  15. 如何自定义 `Global.asax` 中的 `mapRoute`? 
  16. 如何实现表格行的全选和全不选 
  17. 如何显示“正在加载数据” 
  18. 如何使用 jQuery 创建主从表格(master-detail grids)? 

1) 如何在 MVC 中实现高性能的 CRUD 操作?

粗略考虑,所有业务解决方案都具有创建-读取-更新-删除(CRUD)的特性。如果可能,从开发者的角度来看,为“插入”和“更新”使用相同的“保存表单”可能更具成本效益。通过管理发送到操作的参数,可以使用相同的表单。

假设你有一个类似表格的列表,实际上是一个 HTML 表格,并在表单上有一个单独的“新建”按钮。在表格的每一行中,都有一个与该行相关的“编辑”和“删除”按钮。

点击“新建”后,重定向到一个新页面——这里称为视图——并不是一个有效的方法。因为在重定向页面上保存数据后,用户必须点击“显示列表”才能看到插入到数据库中的数据。这意味着重定向列表视图并以可变的查询成本从数据库中选择数据!

而不是上面描述的“点击新建,然后再次列出”的场景,可以执行更好的方法。

Create(创建):

  • 在列表视图中,点击“新建”后,会出现一个“jQuery 保存对话框”。
  • Create 视图被渲染到 jQuery 对话框中。
  • 填写 Create 表单并点击“保存”。
  • 在点击保存按钮时,可以通过 AJAX POST 将数据发送到相关控制器。
  • Ajax 表单有一个 `onSuccess` JavaScript 函数。
  • 在“`onSuccess`”JavaScript 方法中,添加的新行(作为传递给“`onSuccess`”的参数 JSON)会被插入到列表中,而无需刷新整个列表。

Read(读取):

这是一个列表操作。如果可能,列表表单上应只显示所需数据。可以使用以下技术:

  • 通过组合框或数字进行分页,
  • 实现“显示更多”
  • 带有过滤条件的列表。

Update(更新):

  • 在列表视图中,点击列表中任意行的“编辑”后,会出现相同的“jQuery 保存对话框”,并显示选中行的数据。
  • 因为所有步骤都与“创建”相同,所以只需要根据“更新”操作修改“`onSuccess`”方法。
  • 在这种情况下,在数据库更新后,视图中只有被编辑的行的数据会被更新。通过这种方式,无需刷新整个列表即可查看最近编辑的记录。

Delete(删除):

  • 在用一个漂亮的 jQuery 对话框确认后,在数据库删除后,只有选中行会从列表中移除。同样,无需刷新整个列表。

同一个对话框用于插入和编辑。

链接在 `PersonList.cshtml` 视图中如下:

@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,则在对话框中显示该 ID 的数据。
  • newLink:在下面的 jQuery 中使用的虚构类名。
<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>

`PersonController` 中的 Save 操作如下:

// ...

[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 对话框代替 JavaScript 的 confirm 或 alert?

在 Windows 应用程序中可以使用自定义的消息框。对于 Web,可以使用第三方组件库来实现。也可以使用 jQuery 对话框代替 JavaScript 的对话框,如下所示:

`PersonList` 视图中的 Delete 链接如下:

@Html.ActionLink("Delete", "DeletePerson", new { personNo = 
item.PersonNo }, new { @class = "deleteLink", @pkNo = item.PersonNo })

HTML 和 jQuery 代码如下:

<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 列表中实现分页?

分页是列出数据和最小化数据传输成本的良好方法之一。可以执行许多显示数据的方法。在本“如何”中,使用组合框进行分页。但是,如果需要,可以在页面底部显示数字。这取决于应用程序和开发人员。可以使用组合框进行分页,如下所示:

首先,为分页元数据安排好位置,如下所示:

@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>
 
...

在页面首次加载时,使用以下脚本填充 ID 为“`paginginfo`”的 div 并显示第一页记录:

<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 对象中。

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;
  }
  //..

}

当 ID 为“`PageSelect`”的组合框的 `selecteditem` 发生变化时,将运行以下 jQuery 脚本:

//..

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

//..

4) 如何使用 jQuery 实现“显示更多”链接?

这项技术在许多流行的网站中都有使用。它应该在大列表上执行。“显示更多”可以按如下方式实现:

列表视图有一个“更多”链接。

//
 
<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>
 
//

点击“更多”后,将运行以下 jQuery 脚本:

//..

   //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 结果:

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) 如何在链接中使用属性?

这是一种很好的能力,尤其适用于按钮,例如编辑、删除、显示详情等。

在创建列表时,将相关键作为属性附加到链接。点击链接事件时,可以使用该键轻松完成操作。

例如,假设列表中的每一行都有一个删除链接。当点击行中的删除链接时,可以使用该键作为控制器中“删除操作”的参数。

@Html.ActionLink("Delete", "DeletePerson", new { personNo = item.PersonNo }, 
  new { @class = "deleteLink", @pkNo = item.PersonNo })

在客户端检查源代码时,会看到以下行:

<a role="button" class="deleteLink ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" 
  href="https://codeproject.org.cn/Person/DeletePerson/1" pkno="1"><span class="ui-button-text">Delete</span></a>

在 jQuery 脚本中,属性的使用如下。例如,pkno 为 1 并被使用。

$(".deleteLink").live("click", function (e) 
{
      e.preventDefault();
      var pkNo = $(this).attr("pkNo");
      //..
});

6) 如何在 jQuery 中进行 AJAX 调用?

AJAX 调用是提高应用程序速度的一个非常好的能力。在一些数据库数据量大的应用程序中,开发人员必须注意两条数据线上的低数据传输量。第一条线是数据库和应用程序之间,第二条线是应用程序和客户端浏览器之间。对于这类需求,AJAX 调用非常有用。

//..

  $.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 也可以像这样使用:

//..

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

7) 如何在 MVC 中使用 Form collection?

提交表单时,所有表单元素都作为集合发送到控制器中的相关操作。
在控制器中,可以使用每个键值对。假设你有一个如下的保存表单:

@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 提交到控制器中的操作,如下所示:

//..
 
[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) 如何一次删除多条记录?

在某些页面上,一次删除多条记录有时可以使业务更容易。通过收集所有选定记录的键,可以删除多条记录。将所有键发送到控制器后,可以按如下方式执行删除:

首先点击带有“`deleteALL`”ID 的“Delete Selected”按钮。点击“Yes”后,可以使用以下 jQuery 脚本。当然,也可以开发替代脚本。

//..

$("#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 调用“Note”控制器中的“DeleteALL”操作,可以删除多条记录。

9) 如何在 MVC 中使用部分视图操作(partial action)?

在某些情况下,需要在多个表单上使用一个组件。例如,你可能需要在一些单独的表单上有一个“人员信息框”,如下所示:

`_personinfo` 视图可以如下:

@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>

在任何视图中使用部分视图操作,可以使用以下代码行:

//..
 
<h2>Address List</h2>
<div> 
    @Html.Action("_personinfo", "Common") 
</div> 
 
//..

10) 如何在 MVC 应用程序中使用 JSON 格式?

在向控制器操作发送参数和从操作获取结果时,可以使用 JSON 格式。如下所示,Note 控制器中的 DeleteNote 操作有一个 noteNo 参数。这里,pkNo 是一个值传递参数。

$(".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 对象的形式返回结果:

//..
 
[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) 如何填充主从组合框(master-detail combobox)?

某些表单要求在更改一个组合框时填充另一个组合框。例如,对于国家-城市对,国家可以被认为是主,城市是次。

“保存表单”视图中的 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>
}

首次加载时,使用 Address 控制器中的“GetCountryList”操作填充 idCBCountry 组合框。然后,在更改国家组合框时,按如下方式填充城市组合框:

<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 脚本中,列表元素使用索引来访问。

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 使日期类型的处理变得容易。

要在列表中以所需格式显示日期,可以使用以下行:

<span class="BirthDate"> @String.Format("{0:dd.MM.yyyy}", item.BirthDate) </span>

在保存表单中,使用以下 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 一起使用,使用同一页面上的以下脚本:

<script language="javascript" type="text/javascript">
 
 $(document).ready(function () {
    $(".BirthDateSave").datepicker({  
             changeMonth: true,
             changeYear: true,  
             dateFormat: 'dd.mm.yy',
             showOn: 'both'
                   });  
                });

</script>

必须在适当的 .cshtml 文件开头包含以下行:

..
  <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”后,将运行以下脚本:

//..

$(".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;
    }
);

//..

加载到 jQuery 对话框中的 SavePersonPic 表单如下。iframe 用于在 jQuery 对话框中上传文件。

@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>

控制器中用于上传文件的操作如下:

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 --------
    // ..
}

iframe 的 JavaScript “onload”函数如下。上传的图片会在列表的相应行中显示,而无需刷新该行。

//..

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 创建行和单元格,如下所示。从下面的脚本可以看出,在提交此表单后,使用 **saveSuccess** JavaScript 函数来处理这种情况:

..
 
@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)    
    
    ..        
}
 
..

**saveSuccess** JavaScript 方法如下。操作返回一个包含操作类型的 JSON 结果。根据操作(INSERT 或 UPDATE),会修改视图上的表格。当一条新记录添加到数据库时,新的一行会被添加到表格的开头。当一条现有记录在数据库中被更新时,表格中只有相关的行会被修改。

..
 
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="https://codeproject.org.cn/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="https://codeproject.org.cn/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="https://codeproject.org.cn/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="https://codeproject.org.cn/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();
    }
} 
..

表格如下:

//..
 
<table id="personTable">
    <tr>
        <th></th>
        <th>
            #
        </th>
        <th>
            Category
        </th>
        <th>
            FirstName
        </th>
        <th>
            SecondName
        </th>
        <th>
            BirthDate
        </th>
        <th>
            image
        </th>
    </tr>
 
@foreach (var item in Model) {
    <tr id="row-@item.PersonNo">
        <td> 
            @Html.ActionLink("Edit", "Save", 
              new { personNo = item.PersonNo }, new { @class = "editLink" })
            @Html.ActionLink("Addresses", "Index", 
              "Address", new { personNo = item.PersonNo }, new { @class = "adressLink" }) 
            @Html.ActionLink("Notes", "Index", 
              "Note", new { personNo = item.PersonNo }, new { @class = "noteLink" }) 
            @Html.ActionLink("Delete", "DeletePerson", 
              new { personNo = item.PersonNo }, new { @class = "deleteLink", @pkNo = item.PersonNo })
        </td>
 
        <td>
            <span class="PersonNo">@item.PersonNo</span>
        </td>
        <td>
            <span class="CategoryName">@item.CategoryName</span>
        </td>
        <td>
            <span class="FirstName">@item.FirstName</span>             
        </td>
        <td>
            <span class="LastName">@item.LastName</span>
        </td>
        <td> 
            <span class="BirthDate"> @String.Format("{0:dd.MM.yyyy}", item.BirthDate) </span>
        </td>
        <td>
            <img  id="img-@item.PersonNo" height="35px" width="50px" 
              alt="@item.ImgFileName " src="https://codeproject.org.cn/content/images/@item.ImgFileName" />
            <br />
            @Html.ActionLink("Upload Pic", "SavePersonPic", new { personNo = item.PersonNo }, 
              new { @class = "uploadPicLink", @pkNo = item.PersonNo, style = "font-size:9px;" })
        </td>
    </tr>
}
 
</table>
 
//..

上面提到的第一种方法可能看起来是一种旧的方法。因此,以下**第二种方法**可能更可行。在这种方法中,使用渲染的 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>

点击“新建”后,以下脚本会加载到一个 jQuery 对话框中:

@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>
}

当表单提交时,将运行控制器中的以下操作:

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 脚本。

//..

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();
    }
}

//..

saveAddress 表单中 AJAX POST 的 saveSuccess 函数如下:

<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) 如何自定义 `Global.asax` 中的 `mapRoute`?

在经典的 ASP.NET 应用程序中,URL 重写操作可以通过一些第三方程序集轻松完成。在 MVC 应用程序中,可以使用 `Global.asax` 来自定义 `mapRoutes`。

`Global.asax` 中的默认 maproute 如下:

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.ActionLink("Edit", "Save", 
  new { addressNo = item.AddressNo, personNo = item.PersonNo }, new { @class = "editLink" })

上面链接的快照如下:

因此,可以在 `Global.asax` 中添加一个自定义的 maproute 规则,如下所示:

//..
 
routes.MapRoute(
    "AddressSave",
    "Address/Save/{addressNo}/{personNo}",
    new { controller = "Address", action = "Save", 
         addressNo = UrlParameter.Optional, personNo = UrlParameter.Optional }
);
 
//.. 

上述两种技术中的任何一种都可以使用。

16) 如何实现表格行的全选和全不选?

在许多应用程序中,有时需要一次性选中或取消选中表格中的所有复选框,如下所示:


可以使用以下脚本来实现这样的功能:

..

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

..

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

//..
 

        //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:

..
<div id="loadMessage"></div>
..   
可以使用以下 JavaScript 函数来自定义 div 区域:
..

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

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

..   

上述两种技术中的任何一种都可以使用。

18) 如何使用 jQuery 创建主从表格(master-detail grids)? 

点击主行时,详情行会显示在主表格下方,如下所示:
 



以下表格用作网格:

..
<table id="CountryTable" class="hovertable2"></table>
<br />
<br />

<table id="CityTable" class="hovertable"></table>
..    
使用以下 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

.. 

 
结论  

希望本文能有所帮助。

© . All rights reserved.