zoukankan      html  css  js  c++  java
  • 返璞归真 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)]
            
    public 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()]
            
    public 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
            public ActionResult OutputCacheDemo()
            
    {
                
    return Content(DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"));
            }


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


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


            
    // 自定义的 Action Filter 的 Demo
            [MyFilter()]
            
    public 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
        
    {
            
    public override void OnActionExecuting(ActionExecutingContext filterContext)
            
    {
                HttpContext.Current.Response.Write(
    "OnActionExecuting" + "<br />");
            }


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


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


            
    public 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
        
    {
            
    public 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>

            public 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;
                }

            }


            
    附加测试属性


            
    /// <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/")]
            
    public 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
    [源码下载]
  • 相关阅读:
    (二)使用properties配置文件,配置连接数据库的基本信息
    (一)使用properties配置文件,配置连接数据库的基本信息
    使用jdbc连接mysql数据库
    servlet动态资源发布
    JavaWeb静态资源发布
    [leedcode 138] Copy List with Random Pointer
    [leedcode 137] Single Number II
    [leedcode 136] Single Number
    [leedcode 135] Candy
    [leedcode 134] Gas Station
  • 原文地址:https://www.cnblogs.com/webabcd/p/1485893.html
Copyright © 2011-2022 走看看