首页 > 代码库 > 【ASP.Net MVC】AspNet Mvc一些总结

【ASP.Net MVC】AspNet Mvc一些总结

AspNet Mvc一些总结

 

RestaurantReview.cs

using System;using System.Collections.Generic;using System.ComponentModel;using System.ComponentModel.DataAnnotations;using System.Linq;using System.Text.RegularExpressions;using System.Web;using System.Web.Mvc;using Antlr.Runtime;namespace Kwin.AspNetMvc.OdeToFood.Models{    /// <summary>    ///     /// </summary>    /// <remarks>    /// 1.Bind特性用于锁定可以进行模型绑定的属性,    ///     [Bind(Include = "City, Country, Rating")] ,白名单的形式,推荐    ///      [Bind(Exclude = "Id, Name")]                    ,黑名单的形式    ///     /// 可以在三个位置设置:    /// 1.Global.asax.cs 类型列表中设置绑定规则    /// 2.在类定义上<see cref="RestaurantReview"/>    /// 3.在方法参数上    /// --------------------    /// 2.数据验证方法:    /// http://developer.51cto.com/art/201404/435126.htm    /// http://www.cnblogs.com/zhangkai2237/archive/2012/12/12/2814825.html    ///     /// 1).数据验证,方法:实现IDataErrorInfo,演示:<see cref="RestaurantReview"/>    /// 成员函数在UpadtaModel时会被调用,(永远不要相信客户端,服务器这边再检查一遍)    /// --------------------    /// 2).数据验证,方法:继承ValidationAttribute    ///  演示MaxWordsAttribute<see cref="MaxWordsAttribute"/>    /// 这个特性和普通数据注解的区别是普通数据注解仅仅只能验证Model的一个属性,    /// 需要注意的是,自定义的数据注解不支持客户端验证,所有的数据需要提交之后再服务端验证,所以如果要同时实现客户端验证需要自己写js验证    ///     /// 3).数据验证,方法:IValidatableObject      /// 这个接口是为了实现Model的自验证(self-validating)的,是asp.net mvc3 新增的验证特性。    /// 这个特性和普通数据注解的区别是普通数据注解仅仅只能验证Model的一个属性,    /// 而实现了IValidatableObject接口的自验证则在Model的级别来验证    ///     /// 4).人工验证     /// </remarks>    //[Bind(Include = "Id, Name, City, Country, Rating")]    public class RestaurantReview : IValidatableObject // ,IDataErrorInfo    {        Dictionary<string, string> _errorDictionary = new Dictionary<string, string>();        private int rating;        public int Id { get; set; }        [Required(ErrorMessage = "{0}不能为空!LoL")]        [Display(Name = "名称")]        [Remote("CheckNameIsExisted", "Account", HttpMethod = "POST",ErrorMessage = "该用户名已经被使用")]        [MaxWords(10,ErrorMessage = "{0}你输入的太多了")]        //[StringLength(6)]        public string Name { get; set; }           [Required]        [Display(Name = "城市")]        [DisplayFormat(NullDisplayText = "N/A")]        public string City { get; set; }        [Required]        [Display(Name = "国家")]        [DisplayFormat(NullDisplayText = "N/A")]        public string Country { get; set; }        [Required(AllowEmptyStrings = true)]        [Display(Name = "等级")]        [Range(typeof(int),"1","10",ErrorMessage = "{0}必须是{1}和{2}之间的数字")]        public int Rating        {            get { return this.rating; }            set            {                bool IsNum = Regex.IsMatch(Convert.ToString(value), @"^\d+$");                if (!IsNum)                {                    _errorDictionary.Add("Rating", "等级必须是数字");                }                this.rating = value;            }        }                #region IDataErrorInfo Members        /// <summary>        /// 获取一个单一的错误消息,指示对象实例中的错误        /// </summary>        public string Error        {            get            {                return string.Empty; //这里没有实现,返回值一个空的错误消息                            }        }        /// <summary>        /// 用来接收参数和返回一个错误消息指示属性中的错误        /// </summary>        /// <param name="columnName"></param>        /// <returns></returns>        /// <remarks>        /// 服务端再次进行数据验证(原则:永远不要相信客户端)。        /// /UpadtaModel(model)时会调用该方法,        /// 如果返回值不为string.Empty,该返回值会被添加到ModelState.Values属性中,并将        ///        ModelState.IsValid设置为false。        /// </remarks>        public string this[string columnName]        {            get            {                if (_errorDictionary.ContainsKey(columnName))                {                    return _errorDictionary[columnName];                }                return string.Empty;            }        }         #endregion        #region IValidatableObject        /// <summary>        ///         /// </summary>        /// <param name="validationContext"></param>        /// <returns>返回类型是 IEnumerable(一种迭代器接口类型)</returns>        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)        {            if (Rating < 2 && Name.ToLower().Contains("hacker"))            {                yield return new ValidationResult("sorry,Mr.Hacker, you can‘t do this", new[] { "Name" });            }        }        #endregion    }}
View Code

 

        [HttpPost]//Controller中也可以直接接受Post的请求,可以不需要[Httppost]注释:        public ActionResult CheckNameIsExisted(string name)        {            bool result = name != "admin";           return Json(result, JsonRequestBehavior.AllowGet);        }

 

 

ReviewsController.cs

using System;using System.Collections.Generic;using System.ComponentModel.DataAnnotations;using System.Configuration;using System.Data.Objects.DataClasses;using System.Linq;using System.Security.Cryptography;using System.Web;using System.Web.Mvc;using System.Web.Mvc.Html;using Kwin.AspNetMvc.OdeToFood.Models;using PagedList;namespace Kwin.AspNetMvc.OdeToFood.Controllers{    public class ReviewsController : Controller    {        #region 测试数据,        private static bool _hasInitilizeDatas = false;        private static List<RestaurantReview> _restaurantReviews = new List<RestaurantReview>()        {            new RestaurantReview()            {                Id = 1,                Name = "Cidde ha",                City = "shanghai",                Country = "China",                Rating = 10            },            new RestaurantReview()            {                Id = 2,                Name = "张氏",                City = "shanghai",                Country = "中国",                Rating = 8            },            new RestaurantReview()            {                Id = 3,                Name = "Bill",                City = "shanghai",                Country = "UK",                Rating = 6            },            new RestaurantReview()            {                Id = 4,                Name = "Stevien Jason",                City = "shanghai",                Country = "英国",                Rating = 7            }        };        #endregion        public ReviewsController()        {            if (!_hasInitilizeDatas)            {                InitilizeDatas();                _hasInitilizeDatas = true;            }        }        /// <summary>        /// 模拟数据        /// </summary>        private static void InitilizeDatas()        {            Random random = new Random();            for (int i = 1000; i < 2100; i++)            {                RestaurantReview restaurantReview = new RestaurantReview()                {                    Id = i,                    Name = string.Format("老字号餐馆{0}", Convert.ToString(i)),                    //City = "N/A",                    //Country = "N/A",                    Rating = random.Next(1, 10)                };                _restaurantReviews.Add(restaurantReview);            }        }                       public static bool HasInitilizeDatas        {            get { return _hasInitilizeDatas; }            set { _hasInitilizeDatas = value; }        }        public ActionResult Index(string searchKey = null, int currentPage = 1)        {            int pageSize = Convert.ToInt32(ConfigurationManager.AppSettings["pageSzie"]);            var model = _restaurantReviews.Where(                r => searchKey == null || r.Name.ToLower().Contains(searchKey.ToLower().Trim()))                .OrderByDescending(r => r.Rating)                .Select(r => new RestaurantReview()                {                    City = r.City,                    Country = r.Country,                    Id = r.Id,                    Name = r.Name,                    Rating = r.Rating                })                .ToPagedList(currentPage, pageSize); //局限:使用ToPagedList后不能用@Html.DisplayNameFor(model => model.Name)                //.ToList();            if (Request.IsAjaxRequest())            {                System.Threading.Thread.Sleep(1000 * 1);//模拟处理数据需要的时间                //return View(model)会返回整个页面,所以返回部分视图。                return PartialView("_RestaurantPatialView", model);            }            return View(model);        }        //        // GET: /Reviews/Details/5        /// <summary>        ///关于使用System.Web.Mvc.Ajax的说明:        /// Controller的Action方法:        ///    (1)当显式添加[HttpPost],传给System.Web.Mvc.Ajax的AjaxOptions()的HttpMethod只能为 "post",        ///    (2)当显式添加[HttpGet],传给System.Web.Mvc.Ajax的AjaxOptions()的HttpMethod只能为 "get",        ///     (3) 当都没有显式添加[HttpPost]和[HttpGet],传给System.Web.Mvc.Ajax的AjaxOptions()的HttpMethod可以为 "get"也可以为"post",        /// </summary>        /// <param name="id"></param>        /// <returns></returns>        public ActionResult Details(int id=1)        {            var model = (from r in _restaurantReviews                where r.Id == id                select r).FirstOrDefault();            if (Request.IsAjaxRequest())            {                return PartialView("_RestaurantDetails", model);            }                        return View(model);        }        //        // GET: /Reviews/Create        public ActionResult Create()        {            return View();        }        //        // POST: /Reviews/Create        #region FormColletion        //[HttpPost]        //[ValidateAntiForgeryToken]          //public ActionResult Create(FormCollection collection)        //{        //    try        //    {        //        // Add insert logic here        //        if (ModelState.IsValid)        //        {        //            var model = new RestaurantReview();        //            TryUpdateModel(model);        //            _restaurantReviews.Add(model);        //        }        //        return RedirectToAction("Index");        //    }        //    catch        //    {        //        return View();        //    }        //}         #endregion        #region 使用ViewModel实体        /// <summary>        ///         /// </summary>        /// <param name="model"></param>        /// <returns></returns>        /// <remarks>        ///   ValidateAntiForgeryToken特性:        ///      与View中的@Html.AntiForgeryToken()一起使用,        ///   防止CSRF攻击        /// </remarks>        [HttpPost]        [ValidateAntiForgeryToken]         public ActionResult Create(RestaurantReview model)        {            try            {                if (ModelState.IsValid)                {                    _restaurantReviews.Add(model);                }                return RedirectToAction("Index", "Reviews");            }            catch (Exception)            {                return View();            }        }        #endregion        //        // GET: /Reviews/Edit/5        public ActionResult Edit(int id)        {            return View();        }        //        // POST: /Reviews/Edit/5        #region 使用FormCollection        //[HttpPost]        //[ValidateAntiForgeryToken] //与View中的@Html.AntiForgeryToken()一起使用        //public ActionResult Edit(int id, FormCollection collection)        //{        //    try        //    {        //        if (ModelState.IsValid)        //        {        //            //Add update logic here        //            var model = (from r in _restaurantReviews        //                         where r.Id == id        //                         select r).First();        //            TryUpdateModel(model);        //        }        //        return RedirectToAction("Index");        //    }        //    catch        //    {        //        return View();        //    }        //}        #endregion        #region 使用ViewModel实体        /// <summary>        ///         /// </summary>        /// <param name="model"></param>        /// <returns></returns>        /// <remarks>        /// 1.ValidateAntiForgeryToken特性:        ///      与View中的@Html.AntiForgeryToken()一起使用,        ///   防止CSRF攻击        ///         ///2. Bind(Include="....")是用来解决Mass Assignment漏洞        ///   Mass Assignment漏洞演示:        ///   去掉Bind(Include="....")        ///     public ActionResult Edit(RestaurantReview model)        ///         ///   去掉Edit.cshtml中的某个字段如:Name的编辑标签(即:让用户无法修改Name字段)        ///         <div class="editor-field">        ///             @Html.EditorFor(model => model.Name)        ///             @Html.ValidationMessageFor(model => model.Name)        ///         </div>        ///           ///   输入如下连接:        ///   Edit方法路由后面添加参数?Name=hack(Name会自动绑定到模型绑定类型RestaurantReview中的Name属性),        ///   即:        ///   http://localhost:3951/Reviews/Edit/1003?Name=hack        ///           ///   经测试无上面的Mass Assignment,可能新aspnet mvc已经修复该bug        /// </remarks>        [HttpPost]        [ValidateAntiForgeryToken]        //public ActionResult Edit([Bind(Include = "Id, Name,City, Country, Rating")]RestaurantReview model)        public ActionResult Edit(RestaurantReview model)        {            try            {                                if (ModelState.IsValid)                {                       var restaurentView = (from r in _restaurantReviews                            where r.Id == model.Id                            select r).FirstOrDefault();                        TryUpdateModel(restaurentView);                        return RedirectToAction("Index");                }                return View();            }            catch (Exception ex)             {                ModelState.AddModelError("", ex.Message); //给View返回一个错误消息,最终交给@Html.ValidationSummary显示。                return View();            }                    }        #endregion        //        // GET: /Reviews/Delete/5        public ActionResult Delete(int id)        {            var models = from restaurantReview in _restaurantReviews                         where restaurantReview.Id == id                         select restaurantReview;            var model = models.First();            //var model = _restaurantReviews.SingleOrDefault();            return View(model);        }        //        // POST: /Reviews/Delete/5        [HttpPost]        [ValidateAntiForgeryToken]        public ActionResult Delete(int id, FormCollection collection)        {            try            {                // Add delete logic here                var model = (from r in _restaurantReviews                    where r.Id == id                    select r).First();                _restaurantReviews.Remove(model);                return RedirectToAction("Index");            }            catch            {                return View();            }        }        [HttpPost]//Controller中也可以直接接受Post的请求,可以不需要[Httppost]注释:        public ActionResult CheckNameIsExisted(string name)        {            bool result = name != "admin";            return Json(result, JsonRequestBehavior.AllowGet);        }        [ChildActionOnly]        public ActionResult BestReview()        {            var starRestaurent = from r in _restaurantReviews                where r.Rating >= 9                orderby r.Rating descending                 select  r;            return PartialView("_BestReview", starRestaurent.Take(5));        }        /// <summary>        ///         /// </summary>        /// <param name="term"></param>        /// <returns>        ///                   //http://localhost:3951/Reviews/autocompleted?term=老        //返回JSON,如下格式:        //  [        //    {"label":"老字号餐馆1000"},{"label":"老字号餐馆1001"},{"label":"老字号餐馆1002"},        //    {"label":"老字号餐馆1003"},{"label":"老字号餐馆1004"},{"label":"老字号餐馆1005"},        //    {"label":"老字号餐馆1006"},{"label":"老字号餐馆1007"},{"label":"老字号餐馆1008"},{"label":"老字号餐馆1009"}        //  ]        /// </returns>        public ActionResult AutoCompleted(string term)        {            var model = _restaurantReviews.Where(r=>r.Name.ToLower().Contains(term.ToLower().Trim()))                .Take(10)                .Select(r=> new                {                    label = r.Name //匿名对象的字段名必须是label,因为ui.item.label                });            //serialize model into JSON format                         return Json(model,JsonRequestBehavior.AllowGet);        }    }}

Index.cshtml
@*@model IEnumerable<Kwin.AspNetMvc.OdeToFood.Models.RestaurantReview>*@@model IPagedList<RestaurantReview>@{    ViewBag.Title = "我的推荐:餐厅系列";    ViewBag.Message = "美味不断,吃遍填下";}@section mytile{    <section class="featured">        <div class="content-wrapper">            <hgroup class="title">                <h1>@ViewBag.Title</h1><br/>                <h2>@ViewBag.Message</h2>            </hgroup>            <p>            </p>        </div>    </section>}@* -----------1.不用Ajax--------------------------- *@@*<form method="post">        <input type="search" name="searchKey"/>        <input type="submit" value=http://www.mamicode.com/"按名称搜索"/>    </form>*@@* -----------2.System.Web.Mvc.Ajax---------------------------        不用手工为Form添加属性标签,MVC框架自己添加了,    Ajax.BeginForm生成的标签如下:    <form id="form0" method="post"         data-ajax-url="/Reviews"        data-ajax-update="#restaurantList"        data-ajax-mode="replace"        data-ajax-method="post"        data-ajax-loading-duration="2000"        data-ajax-loading="#loding"        data-ajax="true"        action="/Reviews" novalidate="novalidate">    ------------------------------------------------------------------*@    @*@using (Ajax.BeginForm(        new AjaxOptions()        {            HttpMethod = "post",            Url = @Url.Action("Index","Reviews"),            InsertionMode = InsertionMode.Replace,            UpdateTargetId = "restaurantList",            LoadingElementId = "loding",            LoadingElementDuration = 2000        }))    {               <input type="search" name="searchKey"/>        <input type="submit" value=http://www.mamicode.com/"按名称搜索"/>            }*@@* -----------3.Ajax--------------------------------------           需要手工为Form添加些属性标签,用于锚点    模仿MVC框架的构建自己的“非介入式Javascript”模式    生成的form为:    <form data-otf-ajax-updatetarget="#restaurantList"             data-otf-ajax="true"             action="/Reviews"             method="post"             novalidate="novalidate">    -------------------------------------------------------*@<form method="post"      action="@Url.Action("Index")"      data-otf-ajax="true"      data-otf-ajax-updatetarget="#restaurantList">    <input type="search" name="searchKey" data-oft-ajax-autocompleted="@Url.Action("AutoCompleted")" />    <input type="submit" value=http://www.mamicode.com/"按名称搜索" /></form><p>    <strong>        @if (User.Identity.IsAuthenticated)        {            Html.ActionLink("添加餐馆(登录后)", "Create");        }        @Html.ActionLink("添加餐馆", "Create")    </strong></p><div id="loding" hidden="hidden">    <img class="smallLoadingImg" src=http://www.mamicode.com/"@Url.Content("~/Content/images/loading.gif")" /></div>@*Ajax异步更新目标html元素*@<div id="restaurantList">    @{        if (@Model.Any() )        {            //用Html.Partial出现不能显示的问题。原因待查,改用Html.RenderPartial            Html.RenderPartial("_RestaurantPatialView",Model);        }        else        {            <img src=http://www.mamicode.com/"@Url.Content("~/Content/images/NotFoundCryingFace.jpg")"/>            <strong><font color="red">抱歉,没有任何餐馆</font></strong>        }    }</div>
View Code

 

odf.js

$(function () {    /*ajaxFrom*/    var ajaxFormSubmit = function() {        var $form = $(this);        var ajaxOption = {            type: $form.attr("method"),            url: $form.attr("action"),            data: $form.serialize()        };        $.ajax(ajaxOption).done(function(data) {            var updateTargetId = $form.attr("data-otf-ajax-updatetarget");            var $updateTarget = $(updateTargetId);            if ($updateTarget.length > 0) {                var $returnHtml = $(data);                $updateTarget.empty().append(data);                $returnHtml.effect("highlight",6000);            }        });        return false;    };    $("form[data-otf-ajax=‘true‘]").submit(ajaxFormSubmit);    /*AutoCompleted*/    var submitAutoCompleted = function(event, ui) {        var $input = $(this);        $input.val(ui.item.label);        var $form = $input.parents("form:first");        $form.submit();    };    var createAutoCompleted = function() {        var $input = $(this);        var ajaxOption = {            source: $input.attr("data-oft-ajax-autocompleted"), //告诉AutoComplete组件去哪里获取数据            select: submitAutoCompleted,                        //选择某选项后,要处理的逻辑        };        $input.autocomplete(ajaxOption);    }       $("input[data-oft-ajax-autocompleted]").each(createAutoCompleted);    /*分页,使用 PagedList.dll,*/    var getPage = function() {        var $a = $(this);        var ajaxOption = {            url: $a.attr("href"),            type: "post",            data:$("form").serialize()  //把表单中的数据也一起提交,比如,搜索关键字。结果是:在搜索关键字得到的结果上进行分页。        };        $.ajax(ajaxOption).done(function(data) {            var updateTargetId = $a.parents("div.pagedList").attr("data-otf-ajax-updatetarget");            var $updateTarget = $(updateTargetId);            var $returnHtml = $(data);            $updateTarget.empty().append(data);            $returnHtml.effect("highlight", 6000);        });        return false;    }    $(".main-content").on("click", ".pagedList a",getPage);    //$("#Pagination").pagination();});       
View Code

Review.js

$(function() {    $(".isStar").prepend(‘<del class="hot"></del>‘);    //$(".isStar").append(‘<del class="hot"></del>‘);});

 

-----------------------------------

TestAcitonResultController.cs

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;using Kwin.AspNetMvc.OdeToFood.Models;namespace Kwin.AspNetMvc.OdeToFood.Controllers{    public class TestAcitonResultController : Controller    {        [ActionName("RedirectToAction")] //为Action起了别名RedirectToAction,就不能用原来的TestRedirectToAction访问了        public ActionResult TestRedirectToAction()        {            TestModel myTestModel = new TestModel()            {                IntParement = 100,                StringPrarement = "TestModel->StringPrarement"            };            return RedirectToAction("TextRouteParement",                 "TestAcitonResult",                new                {                    id = "12",                    myparementString = "keasy5",                    myparementInt = 30,                    testModel = myTestModel                });        }        public ActionResult TestRedirectToRoute()        {            return RedirectToRoute("Default", new { controller = "Home", action = "ForTestIndex", myparement = "keasy5" });        }        public ActionResult TestFile()        {            return File(Server.MapPath("~/Content/site.css"), "text/css");        }        public ActionResult TestJson()        {            return Json(new {Name = "Keasy5", Laction = "China"},JsonRequestBehavior.AllowGet);        }        public ActionResult TextRouteParement(string myparementString, int myparementInt, [ModelBinder(typeof(TestModelModelBinder))]TestModel testModel)        {            var controller = RouteData.Values["controller"];            var action = RouteData.Values["action"];            var id = RouteData.Values["id"];            var myparement2 = RouteData.Values["myparement"];            var myparementForRequestForm = Request["myparement"]??"N/A";            var messages = string.Format("controller={0},action={1},id={2},myparementString={3}, myparementInt={4},RouteData.Values[\"myparement\"]={5},testModel.IntParement={6},testModel.StringPrarement={7},Request[\"myparement\"]={8}",                controller, action, id, myparementString, myparementInt, myparement2, testModel.IntParement, testModel.StringPrarement, myparementForRequestForm);            return Content(messages);        }    }}
View Code

 

TestModelModelBinder.cs

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;using ModelBindingContext = System.Web.Http.ModelBinding.ModelBindingContext;namespace Kwin.AspNetMvc.OdeToFood.Models{    public class TestModelModelBinder : DefaultModelBinder    {        #region  IModelBinder Members        public override object BindModel(ControllerContext controllerContext, System.Web.Mvc.ModelBindingContext bindingContext)        {            HttpRequestBase requestBase = controllerContext.HttpContext.Request;            TestModel testModel = new TestModel();            testModel.IntParement = Convert.ToInt32(requestBase["IntParement"]);            testModel.StringPrarement = requestBase["IntParement"];/*            var value = http://www.mamicode.com/base.BindModel(controllerContext, bindingContext);>*/            return testModel;        }        #endregion    }}
View Code

 

--------------------------------------------------

TestActionFilerController.cs

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;using Kwin.AspNetMvc.OdeToFood.Filters;namespace Kwin.AspNetMvc.OdeToFood.Controllers{    //[HandleError]可以注释掉因为在FilterConfig已经定义了全局的HandleError,为所有的controller使用了[HandleError]    public class TestActionFilterController : Controller    {        public ActionResult Index()        {            string messages = "TestActionFilterController index";            return Content(messages);        }        [Authorize]        public ActionResult TestAuthorize()        {            string messages = "TestAuthorize";            return Content(messages);        }        public ActionResult TestHandleError(int id = 0)        {            if (id == 0)            {                throw new Exception("我是故意的,测试HandleError用的异常!");            }            /* 默认是显示一个bug异常页面,             * 要是定制显示bug页面,先在web.cofng配置如下节点:             * <system.web>                 <customErrors mode="On"/>*/            return Content("TestHandleError");        }            public ActionResult TestLog()        {            return Content("TestHandleError");        }    }}
View Code

 

---------------------------------------------------

FilterConfig.cs

using System.Web;using System.Web.Mvc;using Kwin.AspNetMvc.OdeToFood.Filters;namespace Kwin.AspNetMvc.OdeToFood{    public class FilterConfig    {        public static void RegisterGlobalFilters(GlobalFilterCollection filters)        {            //在这里定义的是全局的Filter,意味着所有的Controller都启用这里注册的Filter            filters.Add(new HandleErrorAttribute());            filters.Add(new LogAttribute());        }    }}

 

Filters/LogAttribute.cs

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Http.Controllers;using System.Web.Mvc;namespace Kwin.AspNetMvc.OdeToFood.Filters{    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]    public class LogAttribute : ActionFilterAttribute    {        public override void OnActionExecuted(ActionExecutedContext filterContext)        {            base.OnActionExecuted(filterContext);            //写系统日志        }        public override void OnActionExecuting(ActionExecutingContext filterContext)        {            base.OnActionExecuting(filterContext);        }        public override void OnResultExecuted(ResultExecutedContext filterContext)        {            base.OnResultExecuted(filterContext);        }        public override void OnResultExecuting(ResultExecutingContext filterContext)        {            base.OnResultExecuting(filterContext);        }    }}