1. 程式人生 > >ASP.NET MVC使用Action過濾器處理方法

ASP.NET MVC使用Action過濾器處理方法

Action過濾器在動作方法之前及之後執行,Result過濾器在動作結果被執行之前和之後執行。

1、Action過濾器

在ASP.NET MVC中建立MvcApp專案,建立資料夾Filter,然後新建類MyActionFilterAttribute(為了遵循預設的約定,名稱以Attribute結尾),繼承自ActionFilterAttribute類。ActionFilterAttribute類有如下4個方法。

using System;
 
namespace System.Web.Mvc
{
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
    public abstract class ActionFilterAttribute : FilterAttribute, IActionFilter, IResultFilter
    {
 
        protected ActionFilterAttribute();
 
        public virtual void OnActionExecuted(ActionExecutedContext filterContext);
 
        public virtual void OnActionExecuting(ActionExecutingContext filterContext);
 
        public virtual void OnResultExecuted(ResultExecutedContext filterContext);
 
        public virtual void OnResultExecuting(ResultExecutingContext filterContext);
    }
}

實現MyActionFilterAttribute類:

using System;
using System.Web.Mvc;
 
namespace MvcApp.Filter
{
    public class MyActionFilterAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            //1、獲取請求的類名和方法名
            string strController = filterContext.RouteData.Values["controller"].ToString();
            string strAction = filterContext.RouteData.Values["action"].ToString();
 
            //2、用另一種方式獲取請求的類名和方法名
            string strController2 = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
            string strAction2 = filterContext.ActionDescriptor.ActionName;
 
            filterContext.HttpContext.Response.Write("控制器:" + strController + "<br/>");
            filterContext.HttpContext.Response.Write("控制器:" + strController2 + "<br/>");
            filterContext.HttpContext.Response.Write("Action:" + strAction + "<br/>");
            filterContext.HttpContext.Response.Write("Action:" + strAction2 + "<br/>");
 
            filterContext.HttpContext.Response.Write("Action執行前:" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss fff") + "<br/>");
            base.OnActionExecuting(filterContext);
        }
 
        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            filterContext.HttpContext.Response.Write("Action執行後:" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss fff") + "<br/>");
            base.OnActionExecuted(filterContext);
        }
    }
}

對於過濾器,我們可以把它們加在3個地方,一個是控制器上面(控制器下面的所有Action),一個是Action上面(指定標識的Action),另一個就是全域性位置(所有控制器中的Action)。這裡只演示在Action上面和Home控制器中:

[MyActionFilter]
public ActionResult Index()
{
    return View();
}

2、Result過濾器

新建MyResultFilterAttribute類,繼承ActionFilterAttribute:

using System;
using System.Web.Mvc;
 
namespace MvcApp.Filter
{
    public class MyResultFilterAttribute : ActionFilterAttribute
    {
        /// <summary>
        /// 載入“檢視”前執行
        /// </summary>
        /// <param name="filterContext"></param>
        public override void OnResultExecuting(ResultExecutingContext filterContext)
        {
            filterContext.HttpContext.Response.Write("載入檢視前執行 OnResultExecuting" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss fff") + "<br/>");
            base.OnResultExecuting(filterContext);
        }
 
        /// <summary>
        /// 載入“檢視”後執行
        /// </summary>
        /// <param name="filterContext"></param>
        public override void OnResultExecuted(ResultExecutedContext filterContext)
        {
            filterContext.HttpContext.Response.Write("載入檢視後執行 OnResultExecuted" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss fff") + "<br/>");
            base.OnResultExecuted(filterContext);
        }
    }
}

這裡把MyResultFilter過濾器加在控制器上面,相當於給Home控制器中的所有的Action方法添加了MyResultFilter過濾器。

using MvcApp.Filter;
using System.Web.Mvc;
 
namespace MvcApp.Controllers
{
    [MyResultFilter]
    public class HomeController : Controller
    {
        [MyActionFilter]
        public ActionResult Index()
        {
            return View();
        }
    }
}

執行結果,如下圖:

示例:使用Action過濾器,實現操作日誌的記錄功能。

在Models目錄下建立OperateLogModel.cs(操作日誌實體類):

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

namespace MvcApp.Models
{
    /// <summary>
    /// 操作日誌實體類
    /// </summary>
    public class OperateLogModel
    {
        /// <summary>
        /// 控制器名稱
        /// </summary>
        public string ControllerName { get; set; }

        /// <summary>
        /// Action名稱
        /// </summary>
        public string ActionName { get; set; }

        /// <summary>
        /// 功能模組
        /// </summary>
        public string FunctionalModule { get; set; }

        /// <summary>
        /// 操作型別
        /// </summary>
        public string OperationType { get; set; }

        /// <summary>
        /// 操作時間
        /// </summary>
        public DateTime OperationDate { get; set; }

        /// <summary>
        /// 路徑
        /// </summary>
        public string Path { get; set; }

        /// <summary>
        /// 請求引數
        /// </summary>
        public string Params { get; set; }
    }
}

建立Filter目錄,並在該目錄下建立OperateLogAttribute類,繼承ActionFilterAttribute類:

using MvcApp.Models;
using Newtonsoft.Json;
using System;
using System.IO;
using System.Text;
using System.Web;
using System.Web.Mvc;

namespace MvcApp.Filter
{
    /// <summary>
    /// 操作日誌
    /// </summary>
    public class OperateLogAttribute : ActionFilterAttribute
    {
        /// <summary>
        /// 功能模組
        /// </summary>
        public string FunctionalModule { get; set; }

        /// <summary>
        /// 操作型別
        /// </summary>
        public string OperationType { get; set; }

        /// <summary>
        /// 記錄請求日誌
        /// </summary>
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            //建立操作日誌實體類
            OperateLogModel requestLog = new OperateLogModel();
            requestLog.ControllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
            requestLog.ActionName = filterContext.ActionDescriptor.ActionName;
            requestLog.FunctionalModule = this.FunctionalModule;
            requestLog.OperationType = this.OperationType;
            requestLog.OperationDate = DateTime.Now;
            requestLog.Path = filterContext.RequestContext.HttpContext.Request.Path;
            requestLog.Params = GetStrPatams(filterContext.RequestContext.HttpContext.Request);

            //記錄日誌
            string logJson = JsonConvert.SerializeObject(requestLog);
            WriteLog(logJson);
        }

        /// <summary>
        /// 獲取字串引數
        /// </summary>
        public string GetStrPatams(HttpRequestBase theRequest)
        {
            string result = "";
            string url = theRequest.Url.ToString();

            string method = theRequest.HttpMethod;
            if (method == "GET")
            {
                result = theRequest.QueryString.ToString();
            }
            else if (method == "POST")
            {
                result = theRequest.Form.ToString();
            }

            //if (result == "")
            //{
            //    result = theRequest.Params.ToString();
            //}

            if (result.Length > 0)
            {
                result = HttpUtility.UrlDecode(result, Encoding.UTF8);
            }

            return result;
        }

        /// <summary>
        /// 寫入日誌
        /// </summary>
        public void WriteLog(string message)
        {
            string path = AppDomain.CurrentDomain.BaseDirectory + "/MyLog.txt";
            using (StreamWriter sw = new StreamWriter(path, true, Encoding.Default))
            {
                sw.Flush();
                sw.WriteLine("時間:" + DateTime.Now);
                sw.WriteLine("內容:" + message);
                sw.WriteLine("-------------------------");
            }
        }
    }
}

建立OrderController.cs(訂單控制器),編寫新增訂單方法,並在該方法上新增OperateLog特性:

using MvcApp.Filter;
using MvcApp.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MvcApp.Controllers
{
    /// <summary>
    /// 訂單控制器
    /// </summary>
    public class OrderController : Controller
    {
        /// <summary>
        /// 新增訂單
        /// </summary>
        [OperateLog(FunctionalModule = "訂單業務", OperationType = "新增")]
        public bool AddOrder(string orderName, decimal price)
        {
            return true;
        }
    }
}