目录:

  1. 自定义模型IModelBinder
  2. 自定义模型验证
  3. 自定义视图引擎
  4. 自定义Html辅助方法
  5. 自定义Razor辅助方法
  6. 自定义Ajax辅助方法
  7. 自定义控制器扩展
  8. 自定义过滤器
  9. 自定义ActionResult

自定义模型IModelBinder

IModelBinder主要解决的问题是,将请求的数据转换成需要的数据这部分逻辑进行了封装。比如说 http://localhost:4742/Person/Person/2 请求的参数Id是2,通过参数2,获得2相关的所有数据。

这样做的好处是:

  1. 使代码变得更加简洁
  2. 帮助我们获取HTTP请求中的数据
  3. 帮助我们完成必要的数据类型转换

Controller部分:

当访问http://localhost:4742/Person/Person?Name=admin&Age=12时,自动转换为setting对象

[HttpPost]
    public ActionResult Person2([ModelBinder(typeof(SettingsBinder))]Settings settings)
    {       
        return View("Person");
    }

IModelBinder部分

SettingsBinder继承了IModelBinder,并实现了BindModel,通过controllerContext.HttpContext.Request获取请求,从请求中获取参数值,然后转换为对象

public class SettingsBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var request = controllerContext.HttpContext.Request;
        //  从request中获取参数值
        var name = request["Name"];
        var age = request["Age"];
        //  然后将参数值转为对象
        var setting = new { Name = name, Age = age };
        return setting;
    }
}

注:当Person2([ModelBinder(typeof(SettingsBinder))]Settings settings)已存在时,不能再定义Person2方法

自定义验证

通过定义自定义验证特性类,实现View的模型验证,NotEqualTo即自定义验证

public class RegisterModel
    {
        [Required]
        [StringLength(6, MinimumLength = 2)] //
        [Display(Name = "用户名")]
        public string UserName { get; set; }


        [NotEqualTo("UserName", ErrorMessage = "不能与用户名的值相同")]
        public string OtherName { get; set; }

        //  NotEqualTo  是自定义模型验证特性
    }

NotEqualToAttribute继承了ValidationAttribute和IClientValidatable ,并实现了IsValid和GetClientValidationRules方法

通过NotEqualTo构造参数的值UserName,获得该对象对应该参数值的属性值,匹配属性的值和约束的值OtherName是否相等,然后返回结果信息

using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Web.Mvc;

namespace MvcValidation.Extension
{
    //  ValidationAttribute 验证特性
    //  IClientValidatable  客户端验证接口(View视图验证)
    public class NotEqualToAttribute : ValidationAttribute, IClientValidatable
    {
        public string OtherProperty { get; set; }

        //  构造参数
        public NotEqualToAttribute(string otherProperty)
        {
            OtherProperty = otherProperty;
        }

        //  验证方法
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            //从验证上下文中可以获取我们想要的的属性
            var property = validationContext.ObjectType.GetProperty(OtherProperty);
            if (property == null)
            {
                return new ValidationResult(string.Format(CultureInfo.CurrentCulture, "{0} 不存在", OtherProperty));
            }

            //获取属性的值
            var otherValue = property.GetValue(validationContext.ObjectInstance, null);

            //  判断并返回验证结果
            if (object.Equals(value, otherValue))
            {
                return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
            }
            return null;
        }
        //  客户端验证
        public System.Collections.Generic.IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            //  设置客户端验证结果信息
            var rule = new ModelClientValidationRule
            {
                ValidationType = "notequalto",
                ErrorMessage = FormatErrorMessage(metadata.GetDisplayName())
            };
            rule.ValidationParameters["other"] = OtherProperty;
            yield return rule;
        }
    }
}


自定义视图引擎

系统提供了视图和视图引擎,我们需要了解它之后继承并重写它的逻辑。

/*  
     *  思路
     *  1、控制器方法返回ActionResult是一个抽象类 
     *  2、ActionResult的其中一个子类ViewResult,正是她使用IView实例最终渲染出视图 
     *  3、需要自定义IView 
     *  4、IViewEngine管理着IView,同时也需要自定义IViewEngine
     *  5、自定义IViewEngine是需要全局注册的
     */
//namespace System.Web.Mvc

    //public interface IView
    //{
    //  第一个参数ViewContext包含了需要被渲染的信息,被传递到前台的强类型Model也包含在其中。 
    //  第二个参数TextWriter可以帮助我们写出想要的html格式。
    //  void Render(ViewContext viewContent, TextWriter textWriter);
    //}
//namespace System.Web.Mvc
    //public interface IViewEngine
    //{
    //    //  FindPartialView:在当前控制器上下文ControllerContext中找到部分视图。 
    //    System.Web.Mvc.ViewEngineResult FindPartialView(System.Web.Mvc.ControllerContext controllerContext, string partialViewName, bool useCache);
    //    //  FindView:在当前控制器上下文ControllerContext中找到视图。 
    //    System.Web.Mvc.ViewEngineResult FindView(System.Web.Mvc.ControllerContext controllerContext, string viewName, string masterName, bool useCache);
    //    //  ReleaseView:释放当前控制器上下文ControllerContext中的视图。
    //    void ReleaseView(System.Web.Mvc.ControllerContext controllerContext, System.Web.Mvc.IView view);
    //}

我们将派生出它们的类,通过自定义视图引擎类实现渲染,并显示。
准备资源:

public class Student
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Score { get; set; }
    }

    public class DataAccess
    {
        List<Student> students = new List<Student>();

        public DataAccess()
        {
            for (int i = 0; i < 10; i++)
            {
                students.Add(new Student()
                {
                    Id=i+1,
                    Name="Name"+Convert.ToString(i+1),
                    Score = i+80
                });
            }
        }

        public List<Student> GetStudents()
        {
            return students;
        }
    }

自定义扩展

public class StudentView : IView
    {
        /// <summary>
        /// 渲染
        /// 通过获得视图上下文数据,然后自定义输出格式通过TextWriter输出数据
        /// </summary>
        /// <param name="viewContent"></param>
        /// <param name="writer"></param>
        public void Render(ViewContext viewContent, TextWriter writer)
        {
            //  从视图上下文ViewContext拿到model
            var model = viewContent.ViewData.Model;
            var students=model as List<Student>;
            //  自定义输出视图的html格式
            writer.Write("<table border=1><tr><th>编号</th><th>名称</th><th>分数</th></tr>");
            foreach (Student stu in students)
            {
                writer.Write("<tr><td>" + stu.Id + "</td><td>" + stu.Name + "</td><td>" + stu.Score + "</td></tr>");
            }
            writer.Write("</table>");
        }
    }

    public class StudentViewEngine : IViewEngine
    {
        //呈现部分视图
        public ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache)
        {
            throw new NotImplementedException();
        }
        //呈现视图
        public ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
        {
            if (viewName == "StudentView")
            {
                //  呈现自定义视图
                return new ViewEngineResult(new StudentView(), this);
            }
            else
            {
                return new ViewEngineResult(new string[] { "针对Student的视图还没创建!" });
            }
        }
        //显示视图
        public void ReleaseView(ControllerContext controllerContext, System.Web.Mvc.IView view)
        {
            
        }
    }

至此自定义视图引擎完成。接下来我们进行调用:
我们只需要在View中指定自定义视图的名称即可。

public ActionResult Index()
        {
            var students = new DataAccess().GetStudents();
            ViewData.Model = students;

            return View("StudentView");
        }

设置默认的,全局的视图引擎
只需要添加ViewEngines.Engines.Add(new StudentViewEngine());即可实现。

protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);


            ViewEngines.Engines.Add(new StudentViewEngine());
        }

 

自定义HtmlHelper辅助方法

定义扩展方法类和扩展方法

using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

//  设置命名空间为统一的Html命名空间
namespace System.Web.WebPages.Html
{
    //  设置静态类
    public static class HtmlExtensions
    {
        //  为HtmlHelper类提辅助方法Img,参数为src和alt
        public static MvcHtmlString Img(this HtmlHelper html,string src,string alt)
        {
            return MvcHtmlString.Create("<img src=\"" + src + "\" alt=\"" + alt + "\" />");
        }
} }

在View页面中调用该扩展方法

@* 调用Img方法,前者为src,后者为alt,生成的结果是:<img src="C:\images\btn.ico\" alt="" /> *@
@Html.Img("C:\\images\\btn.ico","")

 

自定义Razor辅助方法

在MVC项目根目录下新建一个文件夹名为:App_Code,用于存放MyHelpers.cshtml

Asp.Net Mvc 自定义扩展

编写MyHelpers.cshtml内容如下:

相当于定义了MyHelpers.li(List<string> arrays)方法,通过关键字helper进行声明,这样其他的cshtml页面都可以访问该方法

@helper li(List<string> arrays) { 
    <ul>
        @foreach (var item in arrays)
        {
            <li>@(item)</li>
        }
    </ul>
}

cshtml页面访问li方法

Index.cshtml页面调用:

@MyHelpers.li(new List<string>() { "甲","乙","丙","丁"})

页面输出结果:
Asp.Net Mvc 自定义扩展

自定义AjaxHelper辅助方法

与HtmlHelper扩展一样,为AjaxHelper扩展一个方法Textbox,并设置相应的属性

public static class HtmlExtensions
    {
        //  为HtmlHelper类提辅助方法Img,参数为src和alt
        public static MvcHtmlString Img(this HtmlHelper html, string src, string alt)
        {
            return MvcHtmlString.Create("<img src=\"" + src + "\" alt=\"" + alt + "\" />");
        }

        public static MvcHtmlString Textbox(this AjaxHelper ajaxHelper, string name,  AjaxOptions ajaxOptions, object htmlAttributes)
        {
            //  设置标签名
            var tag = new TagBuilder("input");
            //  设置属性值
            tag.MergeAttribute("name", name);
            tag.MergeAttribute("type", "text");

            tag.MergeAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
            tag.MergeAttributes((ajaxOptions ?? new AjaxOptions()).ToUnobtrusiveHtmlAttributes());
            tag.MergeAttribute("value", ");
            //  输出Html
            return MvcHtmlString.Create(tag.ToString(TagRenderMode.Normal));
        }
    }

View调用:

@Ajax.Textbox("search",
    new AjaxOptions
    {
        Url = @Url.Action("GetTime"),
        UpdateTargetId = "divTime",
        InsertionMode = InsertionMode.Replace
    },
new { size = 50 })

输出结果:
输出结果的源码:Asp.Net Mvc 自定义扩展

<input data-ajax="true" data-ajax-mode="replace" data-ajax-update="#divTime" data-ajax-url="/AjaxHelperExt/GetTime" name="search" size="50" type="text" value="自定义Ajax扩展"></input>

自定义UrlHelper辅助方法

略.

自定义控制器扩展BaseController

//  BaseController  针对Controller进行重写
    //  并且提供了一些公用的方法如权限校验,Action跳转、日志记录等
    public class BaseController : Controller
    {

        protected override void OnException(ExceptionContext filterContext)
        {
            //  处理异常
            base.OnException(filterContext);
        }

        protected override void Initialize(RequestContext requestContext)
        {
            //  处理初始化信息,如Cookie,Session等缓存信息
            base.Initialize(requestContext);
        }

        protected override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            //  在调用操作方法前调用
            base.OnActionExecuting(filterContext);
        }

        protected override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            //  在调用操作方法后调用
            base.OnActionExecuted(filterContext);
        }

        
    }

自定义过滤器

原文

路由访问过滤器

/// <summary>
    /// 路由访问过滤器
    /// </summary>
    public class SystemIActionFilter : IActionFilter
    {
        //  
        // Summary:  
        //     Called after the action method is invoked.  
        //      在Action返回之后  
        // Parameters:  
        //   filterContext:  
        //     Information about the current request and action.  
        public void OnActionExecuted(ActionExecutedContext filterContext)
        {
        }
        //  
        // Summary:  
        //     Called before the action method is invoked.  
        //      在进入Action之前  
        //      说明:使用RedirectToRouteResult进行路由值进行重定向时  
        //      RouteName 路由名称   
        //      RouteValues 路由值  特别注意第三个值 Permanent 获取一个值  
        //      该值指示重定向是否应为永久重定向 如果为true 在本程序会出现问题  
        // Parameters:  
        //   filterContext:  
        //     Information about the current request and action.  
        public void OnActionExecuting(ActionExecutingContext filterContext)
        {
            //验证 控制器 视图   
            string tempAction = filterContext.RouteData.Values["action"].ToString();
            string tempController = filterContext.RouteData.Values["controller"].ToString();
            string tempLoginAction = filterContext.RouteData.Values["action"].ToString();

            if (tempAction == "HomeLogin" && tempController == "Home" || tempLoginAction == "UserLogin" ? false : true)
            {
                //请求登录时  
                if (tempAction == "UserLogin" && tempController == "Home" ? false : true)
                {
                    //Cookie  
                    HttpCookie tempToken = filterContext.HttpContext.Request.Cookies["exclusiveuser_token"];
                    if (tempToken == null)
                    {
                        filterContext.Result = new RedirectToRouteResult("HomeLogin", new RouteValueDictionary(new { controller = "Home", action = "HomeLogin" }), false);
                    }
                    //登录token不为null时  进行合法性验证token 头部,载荷,签名,cookie过期时间  
                    if (tempToken == null ? false : true)
                    {
                        //UserToken 方法 将验证 token 合法性 包括token 签名 ,token载荷,cookie 过期时间等  
                        //string SystemToken = new SecondTrackToken().UserToken();
                        //if (SystemToken == null)
                        //{
                        //    filterContext.Result = new RedirectToRouteResult("HomeLogin", new RouteValueDictionary(new { controller = "Home", action = "HomeLogin" }), false);
                        //};
                    }
                }
            }
        }
    }
路由访问过滤器

相关文章: