当前位置: 首页 > news >正文

Asp.Net MVC4系列--进阶篇之AJAX

本章将开始介绍MVC中Ajax的使用

 

以一个非Ajax版本开始

 

Controller

public class PeopleController : Controller
    {
       private readonly Person[] _personData = {
new Person {FirstName = "Iori",LastName = "Lan", Role = Role.Admin},
new Person {FirstName = "Edwin", LastName= "Sanderson", Role = Role.Admin},
new Person {FirstName = "John",LastName = "Griffyth", Role = Role.User},
new Person {FirstName = "Tik",LastName = "Smith", Role = Role.User},
new Person {FirstName = "Anne",LastName = "Jones", Role = Role.Guest}
};
       public ActionResult Index()
       {
           return View("List");
       }
       public ActionResult GetPeople()
       {
           return View("List",_personData);
       }
       [HttpPost]
       public ActionResult GetPeople(string selectedRole)
       {
           if (selectedRole == null || selectedRole == "All")
           {
                returnView("List",_personData);
           }
           var selected = (Role)Enum.Parse(typeof(Role), selectedRole);
           return View("List",_personData.Where(p => p.Role ==selected));
       }
}


 

Model


 public class Person
    {
       public string FirstName { get; set; }
       public string LastName { get; set; }
       public Role Role { get; set; }
    }
   public enum Role
    {
       Admin,
       User,
       Guest
    }


 

View

@{
   Layout = null;
}
 
@using MVCAjax.Models
@model IEnumerable<Person>
@{
ViewBag.Title = "GetPeople";
}
<h2>Get People</h2>
<table>
<thead><tr><th>First</th><th>Last</th><th>Role</th></tr></thead>
<tbody>
@foreach (var p in Model) {
<tr>
<td>@p.FirstName</td>
<td>@p.LastName</td>
<td>@p.Role</td>
</tr>
}
</tbody>
</table>
@using (Html.BeginForm()) {
<div>
@Html.DropDownList("selectedRole",new SelectList(
new []{"All"}.Concat(Enum.GetNames(typeof(Role)))))
<button type="submit">Submit</button>
</div>
}


测试:


验证请求类型

在IE中打开F12->Network ,我们可以看到请求的发起者是click操作,因为不是xmlHttpRequest,因而不是ajax请求


 

使用Ajax重构代码

配置Unobstrusiveajax

打开web.config

确保这一行在appconfig节点中:

<add key="UnobtrusiveJavaScriptEnabled"  value="true" />


打开App_Start/BundleConfig.cs,确保已添加(默认已添加):

 

bundles.Add(newScriptBundle("~/bundles/jquery").Include(
                       "~/Scripts/jquery-{version}.js"));
 
           bundles.Add(new ScriptBundle("~/bundles/jqueryui").Include(
                       "~/Scripts/jquery-ui-{version}.js"));
 
           bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
                       "~/Scripts/jquery.unobtrusive*",
                        "~/Scripts/jquery.validate*"));


原因:我们需要的是jquery.1.7.1.js 和jquery.unobstrucsive-ajax.min.js,这两个包已经包含了,在layout中render就可以了。

 

打开_layout.cshtml

在<head>中render 这两个包:

 

   @Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/jqueryval")


 

注意:在View确保没有把@{layout=null},否则layout没有应用导致没有renderbundle,以致于无法render需要的script。

 

Controller 添加Action:

public ActionResult AjaxGetPeople()
        {
            return View("AjaxList");
        }
        public PartialViewResult GetPeoplePartial(string selectedRole = "All")
        {
           IEnumerable<Person> data = _personData;
            if(selectedRole != "All")
            {
                var selected = (Role)Enum.Parse(typeof(Role), selectedRole);
                data =_personData.Where(p => p.Role == selected);
            }
            return PartialView("PeoplePartialList",data);
        }


添加PartialViewPeoplePartialList.cshtml :

@using MVCAjax.Models
@model IEnumerable<Person>
@foreach (Person p in Model) {
<tr>
<td>@p.FirstName</td>
<td>@p.LastName</td>
<td>@p.Role</td>
</tr>
}


 

添加View: AjaxList.cshtml :

@using MVCAjax.Models
@model string
@{
ViewBag.Title = "GetPeople";
var ajaxOpts = new AjaxOptions {
UpdateTargetId = "tableBody"
};
}
<h2>Get People</h2>
<table>
<thead><tr><th>First</th><th>Last</th><th>Role</th></tr></thead>
<tbody id="tableBody">
@Html.Action("GetPeoplePartial", new {selectedRole= Model })
</tbody>
</table>
@using(Ajax.BeginForm("GetPeoplePartial",ajaxOpts)) {
<div>
@Html.DropDownList("selectedRole", new SelectList(
new []{"All"}.Concat(Enum.GetNames(typeof(Role)))))
<button  type="submit">Submit</button>
</div>
}


 

运行:


F12->Network 查看请求


可以看到,initiator 为XMLHttpRequest ,验证了请求确实是Ajax。

 

分析Obstrusivejavascript 工作原理

<form action="/People/GetPeoplePartial" data-ajax="true" data-ajax-mode="replace" data-ajax-update="#tableBody" id="form0" method="post">


 

这是MVC Framework生成的form tag,对于unobsrutive javascript 来说,他关心的是data-ajax=”true”和data-ajax开头的attribute,首先找到所有data-ajax=”true”的form,然后根据data-ajax-mode找到data-ajax-update的id(注意,unobstrusivejs 基于Jquery,需要加#)完成局部刷新。

 

Ajax Options

以下列出一些常用的AjaxOptions :

 

Confirm

发起请求前弹出确认框,指定确认框的文字

HttpMethod

请求类型:POST,GET,PUT,DELETE等等

InsertionMode

Replace,Before,After, 默认为Replace

LoadingElementId

请求发出后,收到Server回应前弹出一个loading的div,这里指定div id

LoadingElementDuration

设置loading Div最多显示多少秒

UpdateTargetId

要局部更新的container id

Url

发请求的url

 

Loading 和Confirmation

 

现在稍作改动,给例子加一个Confirmation和loading

准备loading的div和css

Css:

<style type="text/css">
    .popup_background {
        z-index: 10;
        background-color: grey;
        position: fixed;
        top: 0;
        bottom: 0;
        left: 0;
        right: 0;
        opacity: 0.4;
    }
    .popup_loading {
        z-index: 11;
        font-size: 50px;
        top: 400px;
        left: 600px;
        position: absolute;
    }
</style>


仅作为演示,我hard-code了loading div的位置,实际项目中需要调整

 

Html:

<div id="loading" class="popup_background" style="display:none">
    <div class="popup_loading">
        <p>Loading...</p>
    </div>
</div>


 

在AjaxOption中指定Id

var ajaxOpts = new AjaxOptions {
UpdateTargetId = "tableBody" ,
Confirm = "Sure?",
LoadingElementDuration = 2000,
LoadingElementId = "loading"
};


 

在Controller中模拟一个长时间的任务

Sleep 3秒

private void MockLongTimeProcessing()
        {
            Thread.Sleep(3000);
        }


在partialview中调用一下

public PartialViewResult GetPeoplePartial(string selectedRole ="All")
        {
            MockLongTimeProcessing();
...
}


运行,查看效果:


 

 

Ajax链接

Ajax链接的生成很简单。

稍作改动,看一下ajax链接的使用方法,在View(AjaxList.cshtml)中添加:

<div>
@foreach (string role in Enum.GetNames(typeof(Role))) {
<div class="ajaxLink">
@Ajax.ActionLink(role,"GetPeoplePartial",
new {selectedRole= role},
ajaxOpts)
</div>
}
</div>


 

这样就可以了,其实就是调用Ajax.ActionLink函数,设置链接的文字,Action,以及参数,最后一个是AjaxOption,我们用的是前面一个demo的。

 

 

添加对Json的支持

 

改动Controller

和前面的步骤一样,添加两个Action,一个是服务第一次加载页面的 请求,我们返回View,一个是Ajax过来的,我们需要返回JsonResult:

   

    public ActionResult  JsonList()
        {
            return View("JsonList");
        }
        public JsonResult GetPeopleJson(string selectedRole = "All")
        {
            IEnumerable<Person> data = _personData;
            if (selectedRole !="All")
            {
                var selected =(Role)Enum.Parse(typeof(Role), selectedRole);
                data =_personData.Where(p => p.Role == selected);
            }
            return Json(data,JsonRequestBehavior.AllowGet);
        }

添加View:

JsonList.cshtml

 

@using MVCAjax.Models
@model string
@{
ViewBag.Title = "GetPeople";
var ajaxOpts = new AjaxOptions {
UpdateTargetId = "tableBody",
 
};
}
<script type="text/javascript">
    function processData(data) {
        var target =$("#tableBody");
        target.empty();
        for (var i = 0; i <data.length; i++) {
            var person = data[i];
           target.append("<tr><td>" + person.FirstName +"</td><td>"
            + person.LastName +"</td><td>" + person.Role +"</td></tr>");
        }
    }
</script>
<h2>Get Json List</h2>
 
<table>
<thead><tr><th>First</th><th>Last</th><th>Role</th></tr></thead>
<tbody id="tableBody">
@Html.Action("GetPeoplePartial", new {selectedRole = Model })
</tbody>
</table>
 
<div>
@foreach (string role in Enum.GetNames(typeof(Role))) {
<div class="ajaxLink">
@Ajax.ActionLink(role, "GetPeople",
new {selectedRole = role},
new AjaxOptions {
Url = Url.Action("GetPeopleJson", new {selectedRole = role}),
OnSuccess = "processData"
})
</div>
}
</div>


为了简便演示,仅仅展示Json部分,笔者拿掉了Loading和Confirm的部分。

 

代码分析

代码的核心在于OnSuccess = "processData" 。

当Ajax请求成功时,指向processData函数,在这个函数里面,我们拿到id(JqueryId)为#tableBody的表单,清空,手动拼html,并用jquery添加到这个html control中。这部分可以优化,可以选择handlebar.js,knockout.js 等js template。

在table body中调用了@Html.Action("GetPeoplePartial",new {selectedRole = Model }),和前面的原因一样,为了第一次加载时显示出所有人员列表。

 

另外,AjaxOptions中还有其他Callback类型;

OnBegin  : 发请求前

OnFailure :请求失败

OnSuccess :请求成功

OnComplete :请求完毕

 

相关文章:

  • Asp.Net MVC4 系列--进阶篇之Model(1)
  • Windows 7安装过程全体验!(42图)
  • Asp.Net MVC4 系列--进阶篇之Model(2)
  • Windows7下系统实用小工具
  • log4net 使用与配置 每天一份log文件
  • 近期阅读关注(200903)
  • VHD(虚拟磁盘)系统在Windows 7中的加载
  • 图解 Windows 7 Native Boot 全教程
  • Javascript Learning Function(2)
  • Windows 7新功能深入体验
  • Windows 7一些优化调整技巧
  • CLR_VIA_C# 学习笔记(1)
  • 从新版MDT、WAIK和OPK谈Windows 7的部署技术
  • 实用技巧 Windows 7使用新体验
  • 简单的方式实现javascript 小数取整
  • 【399天】跃迁之路——程序员高效学习方法论探索系列(实验阶段156-2018.03.11)...
  • Android组件 - 收藏集 - 掘金
  • CSS 提示工具(Tooltip)
  • oschina
  • React 快速上手 - 06 容器组件、展示组件、操作组件
  • uva 10370 Above Average
  • 爱情 北京女病人
  • 基于Javascript, Springboot的管理系统报表查询页面代码设计
  • 浅谈JavaScript的面向对象和它的封装、继承、多态
  • 微服务框架lagom
  • 我建了一个叫Hello World的项目
  • 吴恩达Deep Learning课程练习题参考答案——R语言版
  • 一些关于Rust在2019年的思考
  • ​LeetCode解法汇总2182. 构造限制重复的字符串
  • (2009.11版)《网络管理员考试 考前冲刺预测卷及考点解析》复习重点
  • (2020)Java后端开发----(面试题和笔试题)
  • (delphi11最新学习资料) Object Pascal 学习笔记---第5章第5节(delphi中的指针)
  • (DenseNet)Densely Connected Convolutional Networks--Gao Huang
  • (pt可视化)利用torch的make_grid进行张量可视化
  • (附源码)springboot教学评价 毕业设计 641310
  • (附源码)springboot码头作业管理系统 毕业设计 341654
  • (附源码)springboot掌上博客系统 毕业设计063131
  • (附源码)ssm高校实验室 毕业设计 800008
  • (三)uboot源码分析
  • (十二)devops持续集成开发——jenkins的全局工具配置之sonar qube环境安装及配置
  • (心得)获取一个数二进制序列中所有的偶数位和奇数位, 分别输出二进制序列。
  • (译) 理解 Elixir 中的宏 Macro, 第四部分:深入化
  • (状压dp)uva 10817 Headmaster's Headache
  • .net core 客户端缓存、服务器端响应缓存、服务器内存缓存
  • .net程序集学习心得
  • .net开发时的诡异问题,button的onclick事件无效
  • @JsonSerialize注解的使用
  • [ C++ ] STL priority_queue(优先级队列)使用及其底层模拟实现,容器适配器,deque(双端队列)原理了解
  • []我的函数库
  • [android] 切换界面的通用处理
  • [android] 天气app布局练习
  • [Android] 修改设备访问权限
  • [Angular] 笔记 21:@ViewChild
  • [Ariticle] 厚黑之道 一 小狐狸听故事
  • [C++从入门到精通] 14.虚函数、纯虚函数和虚析构(virtual)