返璞归真 asp.net mvc (5) - Action Filter, UpdateModel, ModelBinder, Ajax, Unit Test

[索引页]
[源码下载]


返璞归真 asp.net mvc (5) - Action Filter, UpdateModel, ModelBinder, Ajax, Unit Test


作者: webabcd


介绍
asp.net mvc 之 Action Filter, UpdateModel, ModelBinder, Ajax, Unit Test
  • Action Filter - 在 Controller 层对信息做过滤。如何实现自定义的 Action Filter
  • UpdateModel -  根据参数自动为对象的属性赋值
  • ModelBinder - 定义如何绑定 Model,DefaultModelBinder 实现了 IModelBinder ,其可以根据名称自动将参数赋值到对象对应的属性上
  • Ajax -  在 asp.net mvc 中使用 ajax
  • Unit Test -  在 asp.net mvc 中使用单元测试


示例
1、asp.net mvc 自带的 Action Filter 的演示
FilterDemoController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;

using MVC.Models;

namespace MVC.Controllers
{
        // HandleError - 出现异常时跳转到 Error.aspx(先在指定的 view 文件夹找,找不到再在 Shared 文件夹下找)
        // 需要 web.config 配置 - <customErrors mode= "On" />
        [HandleError]
         public class FilterDemoController : Controller
        {
                // 每一个 Filter 都有一个 Order 属性,其用来指定 Filter 的执行顺序

                // [NonAction] - 当前方法为普通方法,不解析为 Action

                // [AcceptVerbs(HttpVerbs)] - 调用该 Action 的 http 方法
                // HttpVerbs 枚举成员如下: HttpVerbs. Get, HttpVerbs.Post, HttpVerbs.Put, HttpVerbs.Delete, HttpVerbs.Head


                ProductSystem ps = new ProductSystem();


                // ActionName() - Action 的名称。默认值同方法名称
                [ActionName( "Product")]

                // ValidateInput() - 相当于 @ Page 的 ValidateRequest, 用于验证请求中是否存在危险代码。可防止 XSS 攻击。默认值为 true
                [ValidateInput( false)]
ActionResult Details() ActionResult Details(int id)
                {
                        var product = ps.GetProduct(id);

                        return View( "Details", product);
                }

                // ValidateAntiForgeryToken() - 避免 CSRF 攻击(需要视图页面中使用 Html.AntiForgeryToken())。原理:生成一个随机字符串,将其同时写入 cookie 和 hidden,当 form 提交到 action 时,验证二者是否相等并且验证提交源是否是本站页面(详查 asp.net mvc 的源代码)
                // 拼 sql 的时候防止 sql 注入:使用 @Parameter 的方式
                [ValidateAntiForgeryToken()]
ActionResult ValidateAntiForgeryTokenTest() ActionResult ValidateAntiForgeryTokenTest()
                {
                        return Content( "ValidateAntiForgeryToken");
                }

                // OutputCache() - 缓存。Duration - 缓存秒数。VaryByParam - none, *, 多个参数用逗号隔开
                [OutputCache(Duration = 10, VaryByParam = "none")]
                // [OutputCache(CacheProfile = "MyCache")] - 通过配置文件对缓存做设置。可以参看 http://www.cnblogs.com/webabcd/archive/2007/02/15/651419.html
ActionResult OutputCacheDemo() ActionResult OutputCacheDemo()
                {
                        return Content(DateTime.Now.ToString( "yyyy-MM-dd hh:mm:ss"));
                }

ActionResult HandleErrorDemo() ActionResult HandleErrorDemo()
                {
                        throw new Exception( "HandleErrorDemo");
                }

                // Authorize() - 验证。走的是 membership
                [Authorize(Users = "user")]
                // [Authorize(Roles = "role")]
                // Request.IsAuthenticated - 返回一个 bool 值,用于指示请求是否通过了验证
ActionResult AuthorizeDemo() ActionResult AuthorizeDemo()
                {
                        return Content( "Authorize");
                }

                // 自定义的 Action Filter 的 Demo
                [MyFilter()]
ActionResult MyFilterDemo() ActionResult MyFilterDemo()
                {
                        return Content( "MyFilterDemo" + "<br />");
                }
        }
}
 
自定的 Action Filter 的实现
MyFilter.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

using System.Web.Mvc;

namespace MVC
{
        /**//// <summary>
        /// 自定义的 Action Filter,需要继承 ActionFilterAttribute
        /// </summary>
         public class MyFilter : ActionFilterAttribute
        {
override void OnActionExecuting() override void OnActionExecuting(ActionExecutingContext filterContext)
                {
                        HttpContext.Current.Response.Write( "OnActionExecuting" + "<br />");
                }

override void OnActionExecuted() override void OnActionExecuted(ActionExecutedContext filterContext)
                {
                        HttpContext.Current.Response.Write( "OnActionExecuted" + "<br />");
                }

override void OnResultExecuting() override void OnResultExecuting(ResultExecutingContext filterContext)
                {
                        HttpContext.Current.Response.Write( "OnResultExecuting" + "<br />");
                }

override void OnResultExecuted() override void OnResultExecuted(ResultExecutedContext filterContext)
                {
                        HttpContext.Current.Response.Write( "OnResultExecuted" + "<br />");
                }
        }
}
 
Details.aspx
<%@ Page Title= "" Language="C# " MasterPageFile="~/Views/Shared/Site.Master " Inherits="System.Web.Mvc.ViewPage<MVC.Models.Products>" %>

<asp:Content ID= "Content1" ContentPlaceHolderID= "TitleContent" runat= "server">
        Details
</asp:Content>
<asp:Content ID= "Content2" ContentPlaceHolderID= "MainContent" runat= "server">
        <% Html.BeginForm( "ValidateAntiForgeryTokenTest", "FilterDemo"); %>
        <%= Html.AntiForgeryToken() %>
        <h2>
                Details</h2>
        <p>
                <strong>ProductID:</strong>
                <%= Html.Encode(Model.ProductID) %>
        </p>
        <p>
                <strong>ProductName:</strong>
                <%= Html.Encode(Model.ProductName) %>
        </p>
        <p>
                <input type= "submit" name= "btnSubmit" value= "submit" />
        </p>
        <% Html.EndForm(); %>
</asp:Content>
 
 
2、应用 UpdateModel 的 Demo
UpdateModelController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;

namespace MVC.Controllers
{
         public class UpdateModelController : Controller
        {
ActionResult Details() ActionResult Details( string name, int age)
                {
                        User user = new User();

                        // UpdateModel() 和 TryUpdateModel() - 系统根据参数自动为对象的属性赋值

                        base.UpdateModel(user); // 失败抛异常
                        // base.TryUpdateModel(user); // 失败不抛异常

                        ViewData.Model = user;

                        return View();
                }
        }
}
 
Details.aspx
<%@ Page Title= "" Language="C# " MasterPageFile="~/Views/Shared/Site.Master " Inherits="System.Web.Mvc.ViewPage<MVC.Controllers.User>" %>

<asp:Content ID= "Content1" ContentPlaceHolderID= "TitleContent" runat= "server">
        Details
</asp:Content>
<asp:Content ID= "Content2" ContentPlaceHolderID= "MainContent" runat= "server">
        <h2>
                Details</h2>
        <p>
                <strong>UserId:</strong>
                <%= Model.ID %>
        </p>
        <p>
                <strong>Name:</strong>
                <%= Model.Name%>
        </p>
        <p>
                <strong>Age:</strong>
                <%= Model.Age%>
        </p>
</asp:Content>
 
 
3、演示什么是 ModelBinder
ModelBinderController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;

namespace MVC.Controllers
{
         public class ModelBinderController : Controller
        {
                /**//// <summary>
                /// 路由过来的或者参数过来的,会自动地赋值到对象的对应的属性上
                /// 做这个工作的就是实现了 IModelBinder 接口的 DefaultModelBinder
                /// </summary>
ActionResult Details() ActionResult Details(User user)
                {
                        base.ViewData.Model = user;

                        // ModelState - 保存 Model 的状态,包括相应的错误信息等
                         if (!base.ModelState.IsValid)
                        {
                                foreach (var state in ModelState)
                                {
                                         if (!base.ModelState.IsValidField(state.Key))
                                                ViewData[ "errorMsg"] = state.Key + "/" + state.Value.Value.AttemptedValue + "<br />";
                                }
                        }

                        return View();
                }
        }
}
 
Details.aspx
<%@ Page Title= "" Language="C# " MasterPageFile="~/Views/Shared/Site.Master " Inherits="System.Web.Mvc.ViewPage" %>

<asp:Content ID= "Content1" ContentPlaceHolderID= "TitleContent" runat= "server">
        Details
</asp:Content>
<asp:Content ID= "Content2" ContentPlaceHolderID= "MainContent" runat= "server">
        <h2>
                Details</h2>
        <% var model = ((MVC.Controllers.User)ViewData.Model); %>
        <p>
                <strong>UserId:</strong>
                <%= model.ID %>
        </p>
        <p>
                <strong>Name:</strong>
                <%= model.Name %>
        </p>
        <p>
                <strong>Age:</strong>
                <%= model.Age %>
        </p>
        <p>
                <strong> error:</strong>
                <%= ViewData[ "errorMsg"] %>
        </p>
</asp:Content>
 
 
4、使用 ajax 的 Demo
        <p>
                Ajax
                
                <script src= "http://www.cnblogs.com/Scripts/MicrosoftAjax.debug.js" type= "text/javascript"></script>
                <script src= "http://www.cnblogs.com/Scripts/MicrosoftMvcAjax.debug.js" type= "text/javascript"></script>
                                                
                <br />
                
                <!-- AjaxHelper 简要说明 -->
                <%= Ajax.ActionLink(
                                 "ProductId 为 1 的详情页",
                                 "Details",
                                 "Product",
                                 new { id = 1 },
                                 new AjaxOptions { UpdateTargetId = "ajax" }
                        )
                %>    
        </p>
        <div id= "ajax" />
 
 
5、在 VS 中做单元测试
ProductControllerTest.cs
using MVC.Controllers;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.VisualStudio.TestTools.UnitTesting.Web;
using System.Web.Mvc;

using MVC.Models;
using System.Collections.Generic;

namespace MVC.Tests
{
        /**//// <summary>
        ///这是 ProductControllerTest 的测试类,旨在
        ///包含所有 ProductControllerTest 单元测试
        ///</summary>
        [TestClass()]
         public class ProductControllerTest
        {
                 private TestContext testContextInstance;

                /**//// <summary>
                ///获取或设置测试上下文,上下文提供
                ///有关当前测试运行及其功能的信息。
                ///</summary>
                 public TestContext TestContext
                {
                         get
                        {
                                return testContextInstance;
                        }
                         set
                        {
                                testContextInstance = value;
                        }
                }

附加测试属性 #region 附加测试属性
                //    
                //编写测试时,还可使用以下属性:
                //
                //使用 ClassInitialize 在运行类中的第一个测试前先运行代码
                //[ClassInitialize()]
static void MyClassInitialize() static void MyClassInitialize(TestContext testContext)
                //{
                //}
                //
                //使用 ClassCleanup 在运行完类中的所有测试后再运行代码
                //[ClassCleanup()]
static void MyClassCleanup() static void MyClassCleanup()
                //{
                //}
                //
                //使用 TestInitialize 在运行每个测试前先运行代码
                //[TestInitialize()]
void MyTestInitialize() void MyTestInitialize()
                //{
                //}
                //
                //使用 TestCleanup 在运行完每个测试后运行代码
                //[TestCleanup()]
void MyTestCleanup() void MyTestCleanup()
                //{
                //}
                //
                #endregion


                /**//// <summary>
                ///Index 的测试
                ///</summary>
                // TODO: 确保 UrlToTest 属性指定一个指向 ASP.NET 页的 URL(例如,
                // http:///Default.aspx)。这对于在 Web 服务器上执行单元测试是必需的,
                //无论要测试页、Web 服务还是 WCF 服务都是如此。
                [TestMethod()]
                [HostType( "ASP.NET")]
                [AspNetDevelopmentServerHost( "C:\\MVC\\MVC", "/")]
                [UrlToTest( "http://localhost:2005/")]
void IndexTest() void IndexTest()
                {
                        ProductController target = new ProductController(); // TODO: 初始化为适当的值
                        int pageIndex = 0; // TODO: 初始化为适当的值

                        ViewResult actual;
                        actual = target.Index(pageIndex) as ViewResult;

                        Assert.AreNotEqual(actual.ViewData.Model as List<Products>, null);
                }
        }
}
 
 
OK
[源码下载]

你可能感兴趣的:(Ajax,mvc,filter,unit,action)