zoukankan      html  css  js  c++  java
  • ASP.NET MVC案例教程(基于ASP.NET MVC beta)——第五篇:MVC整合Ajax

    摘要
          本文将从完成“输入数据验证”这个功能出发,逐渐展开ASP.NET MVC与Ajax结合的方法。首先,本文将使用ASP.NET MVC提供的同步方式完成数据验证。而后,将分别结合ASP.NET AJAX和JQuery将这个功能重构成异步形式。

    数据验证
          在上一篇文章中,我们完成了发布公告的功能。但是从健壮性角度看,这个功能并不完善,因为一般情况下,我们输入的数据要符合一定的约束条件,例如,在我们的例子中,我们至少不能将空字符串作为标题或内容吧。下面,我们来为程序加入数据验证功能,
          ASP.NET MVC中提供了良好的数据验证实现支持,下面我们来看实现过程。首先,我们要修改一下Release.aspx视图,修改后的视图如下。
    Release.aspx:
     1<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Release.aspx.cs" Inherits="MVCDemo.Views.Announce.Release" %>
     2<%@ Import Namespace="MVCDemo.Models.Entities" %>
     3
     4<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
     5
     6<html xmlns="http://www.w3.org/1999/xhtml" >
     7<head runat="server">
     8    <title></title>
     9</head>
    10<body>
    11    <% SelectList categories = ViewData["Categories"as SelectList; %>
    12    <div>
    13        <h1>MVC公告发布系统——发布公告</h1>
    14        <% Html.BeginForm("DoRelease","Announce",FormMethod.Post); %>
    15        <dl>
    16            <dt>标题:</dt>
    17            <dd><%= Html.TextBox("Title"%></dd>
    18            <dd><%= Html.ValidationMessage("TitleValidator"%></dd>
    19            <dt>分类:</dt>
    20            <dd><%= Html.DropDownList("Category",categories) %></dd>
    21            <dd></dd>
    22            <dt>内容:</dt>
    23            <dd><%= Html.TextArea("Content"%></dd>
    24            <dd><%= Html.ValidationMessage("ContentValidator"%></dd>
    25        </dl>
    26        <input type="submit" value="发布" />
    27        <% Html.EndForm(); %>
    28    </div>
    29</body>
    30</html>

          可以看到,并没有什么大的变动,只是多了两个Html.ValidationMessage方法。可以这样理解,这个方法相当于产生一个span标签,而这个span就是要显示错误信息的地方。这个方法接收一个参数,用来指明其在Controller中的名字。如果你对这个迷惑,不要紧,接下来看完Controller的代码,你就什么都清楚了。
    AnnounceController.cs:
     1using System;
     2using System.Collections.Generic;
     3using System.Linq;
     4using System.Web;
     5using System.Web.Mvc;
     6using System.Web.Mvc.Ajax;
     7using MVCDemo.Models;
     8using MVCDemo.Models.Interfaces;
     9using MVCDemo.Models.Entities;
    10
    11namespace MVCDemo.Controllers
    12{
    13    public class AnnounceController : Controller
    14    {
    15        public ActionResult Release()
    16        {
    17            ICategoryService cServ = ServiceBuilder.BuildCategoryService();
    18            List<CategoryInfo> categories = cServ.GetAll();
    19            ViewData["Categories"= new SelectList(categories, "ID""Name");
    20            return View("Release");
    21        }

    22
    23        public ActionResult DoRelease()
    24        {
    25            if (String.IsNullOrEmpty(Request.Form["Title"]) || String.IsNullOrEmpty(Request.Form["Content"]))
    26            {
    27                if (String.IsNullOrEmpty(Request.Form["Title"]))
    28                {
    29                    ViewData.ModelState.AddModelError("TitleValidator","公告标题不能为空!");
    30                }

    31                if (String.IsNullOrEmpty(Request.Form["Content"]))
    32                {
    33                    ViewData.ModelState.AddModelError("ContentValidator""公告内容不能为空!");
    34                }

    35
    36                return Release();
    37            }

    38
    39            AnnounceInfo announce = new AnnounceInfo()
    40            {
    41                ID = 1,
    42                Title = Request.Form["Title"],
    43                Category = Int32.Parse(Request.Form["Category"]),
    44                Content = Request.Form["Content"],
    45            }
    ;
    46
    47            IAnnounceService aServ = ServiceBuilder.BuildAnnounceService();
    48            aServ.Release(announce);
    49
    50            ViewData["Announce"= announce;
    51            return View("ReleaseSucceed");
    52        }

    53    }

    54}

          可以看到,我们的DoRelease这个Action方法多了不少东西。我们看多了什么:当从表单传递过来的标题或内容为空时,我们做了一定处理。注意,这个ViewData.ModelState.AddModelError方法,它就是往我们刚才说的由Html.ValidationMessage生成的span里加入错误信息的方法,它可以有两个参数,第一个指明哪个span,这个参数Html.ValidationMessage中的参数是对应的。第二个参数就是要显示的信息。
          相信结合视图和控制器,已经很好理解了。最后,如果标题或内容有空值的话,我们不再调用业务逻辑组件处理了,而是调用了Release这个Action。为什么我们不用Redirect呢?因为我们要保持ViewData中的数据,刚才我们的错误信息可都放在里面的,而使用了Redirect,ViewData的信息就传不过去了。
          现在,我们再来发布公告。我们故意什么都不填,提交,看结果:
     
          没有问题,我们的程序成功对标题和内容进行了完整性检测(这里就是均不能为空),在验证不通过时,返回了发布公告视图并正确显示了错误提示信息。
          也许你有一个疑问,为什么第一次请求Release视图时没有显示任何错误信息呢?因为那时ViewData中的ModelError是空的。而Html.ValidationMessage生成的标签会自动寻找ModelError中同名的错误信息,找不到,当然是空的了。而在提交空信息时,DoRelease这个Action为ViewData的ModelError添加了内容,于是当再次返回Release视图时,相应信息就显示在我们指定的位置了。

    使用ASP.NET AJAX实现客户端数据验证
          上面的代码运行起来没问题,也达到了我们的要求。但是验证标题内容是否为空这种行为在客户端应该就可以完成。当然,为了放置恶意攻击或浏览器将JavaScript屏蔽的情况,我们应该在后台进行验证,但是我们不能每次都将这种请求发到后台去验证,这太费资源了,毕竟恶意攻击者和JavaScript被屏蔽的浏览器只是少数。所以,在数据被送到后台前,我们应该先进行一遍验证,这样可以节约很多资源。
          下面,我们使用ASP.NET AJAX框架完成客户端的数据验证。
          说实话,在ASP.NET MVC中使用ASP.NET AJAX或JQuery实在太方便了,不信你展开Scripts文件夹,看到没,微软已经把这些库放到里面了,所以,我们要做的只是直接引用。看我们修改后的Release.aspx。
    Release.aspx:
     1<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Release.aspx.cs" Inherits="MVCDemo.Views.Announce.Release" %>
     2<%@ Import Namespace="MVCDemo.Models.Entities" %>
     3
     4<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
     5
     6<html xmlns="http://www.w3.org/1999/xhtml" >
     7<head runat="server">
     8    <title></title>
     9    <script type="text/javascript" src="<%= Url.Content("~/Scripts/MicrosoftAjax.debug.js") %>"></script>
    10    <script type="text/javascript" src="<%= Url.Content("~/Scripts/MicrosoftAjaxValidate.js") %>"></script>
    11</head>
    12<body>
    13    <% SelectList categories = ViewData["Categories"] as SelectList; %>
    14    <div>
    15        <h1>MVC公告发布系统——发布公告</h1>
    16        <% Html.BeginForm("DoRelease","Announce",FormMethod.Post); %>
    17        <dl>
    18            <dt>标题:</dt>
    19            <dd><%= Html.TextBox("Title"%></dd>
    20            <dd><span id="TitleValidator"></span></dd>
    21            <dt>分类:</dt>
    22            <dd><%= Html.DropDownList("Category",categories) %></dd>
    23            <dd></dd>
    24            <dt>内容:</dt>
    25            <dd><%= Html.TextArea("Content"%></dd>
    26            <dd><span id="ContentValidator"></span></dd>
    27        </dl>
    28        <input id="Submit" type="submit" value="发布" />
    29        <% Html.EndForm(); %>
    30    </div>
    31</body>
    32</html>

          改动有两处,首先我们在页头引用了两个js文件,第一个是ASP.NET AJAX的库文件,第二个就是我们一会要实现的包含验证代码的js文件了。你可能注意到那个Url.Content了,Url是ViewPage的一个对象,它最常用的一个方法就是Content,它的功能是返回某个文件的路径。一般情况下,在使用了ASP.NET MVC后,目录结构变得有点诡异,像js、css、图片等与路径(即使是相对路径)引用相关的地方可能会出现问题,但是,只要你在这些地方用Url.Content生成路径,而不是直接将路径写在页面里,一般就没什么问题了。所以,凡是引用js、css、图片等除,请一定使用Url.Content生成路径,其参数只有一个,就是文件原始的相对路径。
          下一个改动就是显示错误信息的span不再是Html.ValidationMessage生成的了,而是普通的span。
          下面我们在Scripts目录下新建MicrosoftAjaxValidate.js文件。
    MicrosoftAjaxValidate.js:
     1Sys.Application.add_init(onPageInit);
     2
     3function onPageInit() {
     4    $addHandler($get("Submit"), "click", validate);
     5}

     6
     7function validate() {
     8    if ($get("Title").value == "" || $get("Content").value == ""{
     9        if ($get("Title").value == ""{
    10            $get("TitleValidator").innerHTML = "标题不能为空!";
    11        }

    12        if ($get("Content").value == ""{
    13            $get("ContentValidator").innerHTML = "内容不能为空!";
    14        }

    15
    16        return false;
    17    }

    18
    19    return true;
    20}

          关于这段代码我不多说了,对ASP.NET AJAX有兴趣的可以参看《ASP.NET AJAX客户端编程之旅》系列文章。
          现在运行,将标题和内容留空,提交。OK!效果和刚才很像,只不过这次是在客户端验证了,并没有提交到服务器端。

    整合JQuery
          下面我们再使用JQuery实现这个功能。
          其实看懂上面的实现后,我想你已经想到怎么整合JQuery了,无非也是引入相应库和js文件,然后使用JQuery编写验证代码。修改后的Release.aspx就没必要看了,无非是引入Scripts目录下的JQuery库,然后再引入一个自定义验证js文件,我们姑且叫JQueryValidate.js吧。
          下面在Scripts目录下新建JQueryValidate.js,代码如下。
    JQueryValidate.js:
     1$(document).ready(function(){
     2    $("#Submit").click(function() {
     3        if ($("#Title").attr("value"== "" || $("#Content").attr("value"== ""{
     4            if ($("#Title").attr("value"== ""{
     5                $("#TitleValidator").attr("innerHTML""标题不能为空!");
     6            }

     7            if ($("#Content").attr("value"== ""{
     8                $("#ContentValidator").attr("innerHTML""内容不能为空!");
     9            }

    10
    11            return false;
    12        }

    13
    14        return true;
    15    }

    16    );
    17}

    18);

    小结
          从本文可以看出,在MVC框架中整合Ajax和普通应用差别不大,唯一就是注意在引用外部js时使用Url.Content方法处理一下相对路径。其实在本文中我们并没有使用到Ajax,而仅仅是整合了JavaScirpt,但是这已经足够了,因为Ajax无非就是在这些JavaScript里包含了异步后台调用。
          其实,ASP.NET MVC有专门针对ASP.NET AJAX的扩展,放在MicrosoftMvcAjax.js里。而在ViewPage里有个叫Ajax的AjaxHelper对象,可以实现一些简单的异步调用。但是这个扩展的功能很有限,有兴趣的可以自己研究一下。我个人还是建议大家自己写JS代码,当然可以使用ASP.NET AJAX或JQeury这样优秀的框架。
          这篇文章先到这里,下一篇中我们讨论一下拦截器的使用。^_^
  • 相关阅读:
    iOS 面试题搜集
    iOS 常用第三方类库、完整APP示例
    iOS 键盘遮挡输入 解决办法
    iOS UIColor RGB HEX
    iOS APP性能优化
    iOS Swift 数组 交换元素的两种方法
    iOS CoreData primitive accessor
    iOS Start developing ios apps (OC) pdf
    iOS 传值方式
    iOS IB_DESIGNABLE IBInspectable @IBDesignable @IBInspectable 加速UI开发
  • 原文地址:https://www.cnblogs.com/luluping/p/1387934.html
Copyright © 2011-2022 走看看