国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - ASP.NET教程 - 詳解ASP.NET MVC 常用擴展點:過濾器、模型綁定

詳解ASP.NET MVC 常用擴展點:過濾器、模型綁定

2020-05-04 15:35心態要好 ASP.NET教程

本篇文章主要介紹了詳解ASP.NET MVC 常用擴展點:過濾器、模型綁定,非常具有實用價值,需要的朋友可以參考下

一、過濾器(Filter)

ASP.NET MVC中的每一個請求,都會分配給對應Controller(以下簡稱“控制器”)下的特定Action(以下簡稱“方法”)處理,正常情況下直接在方法里寫代碼就可以了,但是如果想在方法執行之前或者之后處理一些邏輯,這里就需要用到過濾器。

常用的過濾器有三個:Authorize(授權過濾器),HandleError(異常過濾器),ActionFilter(自定義過濾器),對應的類分別是:AuthorizeAttribute、HandleErrorAttribute和ActionFilterAttribute,繼承這些類并重寫其中方法即可實現不同的功能。

1.Authorize授權過濾器

授權過濾器顧名思義就是授權用的,授權過濾器在方法執行之前執行,用于限制請求能不能進入這個方法,新建一個方法:

?
1
2
3
4
public JsonResult AuthorizeFilterTest()
{
 return Json(new ReturnModel_Common { msg = "hello world!" });
}

直接訪問得到結果:

詳解ASP.NET MVC 常用擴展點:過濾器、模型綁定

現在假設這個AuthorizeFilterTest方法是一個后臺方法,用戶必須得有一個有效的令牌(token)才能訪問,常規做法是在AuthorizeFilterTest方法里接收并驗證token,但是這樣一旦方法多了,每個方法里都寫驗證的代碼顯然不切實際,這個時候就要用到授權過濾器:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class TokenValidateAttribute : AuthorizeAttribute
  {
    /// <summary>
    /// 授權驗證的邏輯處理。返回true則通過授權,false則相反
    /// </summary>
    /// <param name="httpContext"></param>
    /// <returns></returns>
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
      string token = httpContext.Request["token"];
      if (string.IsNullOrEmpty(token))
      {
        return false;
      }
      else
      {
        return true;
      }
    }
  }

新建了一個繼承AuthorizeAttribute的類,并重寫了其中的AuthorizeCore方法,這段偽代碼實現的就是token有值即返回true,沒有則返回false,標注到需要授權才可以訪問的方法上面:

?
1
2
3
4
5
[TokenValidate]
public JsonResult AuthorizeFilterTest()
{
  return Json(new ReturnModel_Common { msg = "hello world!" })
}

標注TokenValidate后,AuthorizeCore方法就在AuthorizeFilterTest之前執行,如果AuthorizeCore返回true,那么授權成功執行AuthorizeFilterTest里面的代碼,否則授權失敗。不傳token:

詳解ASP.NET MVC 常用擴展點:過濾器、模型綁定

傳token:

詳解ASP.NET MVC 常用擴展點:過濾器、模型綁定

不傳token授權失敗時進入了MVC默認的未授權頁面。這里做下改進:不管授權是成功還是失敗都保證返回值格式一致,方便前端處理,這個時候重寫AuthorizeAttribute類里的HandleUnauthorizedRequest方法即可:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/// <summary>
/// 授權失敗處理
/// </summary>
/// <param name="filterContext"></param>
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
  base.HandleUnauthorizedRequest(filterContext);
 
  var json = new JsonResult();
  json.Data = new ReturnModel_Common
  {
    success = false,
    code = ReturnCode_Interface.Token過期或錯誤,
    msg = "token expired or error"
  };
  json.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
  filterContext.Result = json;
}

效果:

詳解ASP.NET MVC 常用擴展點:過濾器、模型綁定

實戰:授權過濾器最廣泛的應用還是做權限管理系統,用戶登錄成功后服務端輸出一個加密的token,后續的請求都會帶上這個token,服務端在AuthorizeCore方法里解開token拿到用戶ID,根據用戶ID去數據庫里查是否有請求當前接口的權限,有就返回true,反之返回false。這種方式做授權,相比登錄成功給Cookie和Session的好處就是一個接口PC端、App端共同使用。

2.HandleError異常過濾器

異常過濾器是處理代碼異常的,在系統的代碼拋錯的時候執行,MVC默認已經實現了異常過濾器,并且注冊到了App_Start目錄下的FilterConfig.cs:

?
1
filters.Add(new HandleErrorAttribute());

這個生效于整個系統,任何接口或者頁面報錯都會執行MVC默認的異常處理,并返回一個默認的報錯頁面:Views/Shared/Error(程序發到服務器上報錯時才可以看到本頁面,本地調試權限高,還是可以看到具體報錯信息的)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@{
  Layout = null;
}
<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <meta name="viewport" content="width=device-width" />
  <title>錯誤</title>
</head>
<body>
  <hgroup>
    <h1>錯誤。</h1>
    <h2>處理你的請求時出錯。</h2>
  </hgroup>
</body>
</html>

默認的異常過濾器顯然無法滿足使用需求,重寫下異常過濾器,應付項目實戰中的需求:

1)報錯可以記錄錯誤代碼所在的控制器和方法,以及報錯時的請求參數和時間;

2)返回特定格式的JSON方便前端處理。因為現在系統大部分是ajax請求,報錯了返回MVC默認的報錯頁面,前端不好處理

新建一個類LogExceptionAttribute繼承HandleErrorAttribute,并重寫內部的OnException方法:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public override void OnException(ExceptionContext filterContext)
{
  if (!filterContext.ExceptionHandled)
  {
    string controllerName = (string)filterContext.RouteData.Values["controller"];
    string actionName = (string)filterContext.RouteData.Values["action"];
    string param = Common.GetPostParas();
    string ip = HttpContext.Current.Request.UserHostAddress;
    LogManager.GetLogger("LogExceptionAttribute").Error("Location:{0}/{1} Param:{2}UserIP:{3} Exception:{4}", controllerName, actionName, param, ip, filterContext.Exception.Message);
 
    filterContext.Result = new JsonResult
    {
      Data = new ReturnModel_Common { success = false, code = ReturnCode_Interface.服務端拋錯, msg = filterContext.Exception.Message },
      JsonRequestBehavior = JsonRequestBehavior.AllowGet
    };
  }
  if (filterContext.Result is JsonResult)
    filterContext.ExceptionHandled = true;//返回結果是JsonResult,則設置異常已處理
  else
    base.OnException(filterContext);//執行基類HandleErrorAttribute的邏輯,轉向錯誤頁面
}

異常過濾器就不像授權過濾器一樣標注在方法上面了,直接到App_Start目錄下的FilterConfig.cs注冊下,這樣所有的接口都可以生效了:

?
1
filters.Add(new LogExceptionAttribute());

異常過濾器里使用了NLog作為日志記錄工具,Nuget安裝命令:

?
1
2
Install-Package NLog
Install-Package NLog.Config

相比Log4net,NLog配置簡單,僅幾行代碼即可,NLog.config:

?
1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <targets>
  <target xsi:type="File" name="f" fileName="${basedir}/log/${shortdate}.log" layout="${uppercase:${level}} ${longdate} ${message}" />
  <target xsi:type="File" name="f2" fileName="D:\log\MVCExtension\${shortdate}.log" layout="${uppercase:${level}} ${longdate} ${message}" />
 </targets>
 <rules>
  <logger name="*" minlevel="Debug" writeTo="f2" />
 </rules>
</nlog>

如果報錯,日志就記錄在D盤的log目錄下的MVCExtension目錄下,一個項目一個日志目錄,方便管理。全部配置完成,看下代碼:

?
1
2
3
4
5
public JsonResult HandleErrorFilterTest()
{
  int i = int.Parse("abc");
  return Json(new ReturnModel_Data { data = i });
}

字符串強轉成int類型,必然報錯,頁面響應:

詳解ASP.NET MVC 常用擴展點:過濾器、模型綁定

同時日志也記錄下來了:

詳解ASP.NET MVC 常用擴展點:過濾器、模型綁定

3.ActionFilter自定義過濾器

自定義過濾器就更加靈活了,可以精確的注入到請求前、請求中和請求后。繼承抽象類ActionFilterAttribute并重寫里面的方法即可:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class SystemLogAttribute : ActionFilterAttribute
{
  public string Operate { get; set; }
 
  public override void OnActionExecuted(ActionExecutedContext filterContext)
  {
    filterContext.HttpContext.Response.Write("<br/>" + Operate + ":OnActionExecuted");
    base.OnActionExecuted(filterContext);
  }
 
  public override void OnActionExecuting(ActionExecutingContext filterContext)
  {
    filterContext.HttpContext.Response.Write("<br/>" + Operate + ":OnActionExecuting");
    base.OnActionExecuting(filterContext);
  }
 
  public override void OnResultExecuted(ResultExecutedContext filterContext)
  {
    filterContext.HttpContext.Response.Write("<br/>" + Operate + ":OnResultExecuted");
    base.OnResultExecuted(filterContext);
  }
 
  public override void OnResultExecuting(ResultExecutingContext filterContext)
  {
    filterContext.HttpContext.Response.Write("<br/>" + Operate + ":OnResultExecuting");
    base.OnResultExecuting(filterContext);
  }
}

這個過濾器適合做系統操作日志記錄功能:

?
1
2
3
4
5
6
[SystemLog(Operate = "添加用戶")]
public string CustomerFilterTest()
{
  Response.Write("<br/>Action 執行中...");
  return "<br/>Action 執行結束";
}

看下結果:

詳解ASP.NET MVC 常用擴展點:過濾器、模型綁定

四個方法執行順序:OnActionExecuting—>OnActionExecuted—>OnResultExecuting—>OnResultExecuted,非常精確的控制了整個請求過程。

實戰中記錄日志過程是這樣的:在OnActionExecuting方法里寫一條操作日志到數據庫里,全局變量存下這條記錄的主鍵,到OnResultExecuted方法里說明請求結束了,這個時候自然知道用戶的這個操作是否成功了,根據主鍵更新下這條操作日志的是否成功字段。

二、模型綁定(ModelBinder)

先看一個普通的方法:

?
1
2
3
4
public ActionResult Index(Student student)
{
  return View();
}

這個方法接受的參數是一個Student對象,前端傳遞過來的參數跟Student對象里的屬性保持一直,那么就自動被綁定到這個對象里了,不需要在方法里new Student這個對象并挨個綁定屬性了,綁定的過程由MVC中的DefaultModelBinder完成的,DefaultModelBinder同時繼承了IModelBinder接口,現在就利用IModelBinder接口和DefaultModelBinder來實現更加靈活的模型綁定。

場景一、前端傳過來了一個加密的字符串token,方法里需要用token里的某些字段,那就得在方法里接收這個字符串、解密字符串、轉換成對象,這樣一個方法還好說,多了的話重復代碼非常多,就算提取通用方法,還是要在方法里調用這個通用方法,有沒有辦法直接在參數里就封裝好這個對象?

模型綁定的對象:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class TokenModel
{
  /// <summary>
  /// 主鍵
  /// </summary>
  public int Id { get; set; }
 
  /// <summary>
  /// 姓名
  /// </summary>
  public string Name { set; get; }
 
  /// <summary>
  /// 簡介
  /// </summary>
  public string Description { get; set; }
 
}

新建一個TokenBinder繼承IModelBinder接口并實現其中的BindModel方法:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class TokenBinder : IModelBinder
{
  public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
  {
    var token = controllerContext.HttpContext.Request["token"];
    if (!string.IsNullOrEmpty(token))
    {
      string[] array = token.Split(':');
      if (array.Length == 3)
      {
        return new TokenModel() { Id = int.Parse(array[0]), Name = array[1], Description = array[2] };
      }
      else
      {
        return new TokenModel() { Id = 0 };
      }
    }
    else
    {
      return new TokenModel() { Id = 0 };
    }
  }
}

這個方法里接收了一個token參數,并對token參數進行了解析和封裝。代碼部分完成了需要到Application_Start方法里進行下注冊:

?
1
ModelBinders.Binders.Add(typeof(TokenModel), new TokenBinder());

現在模擬下這個接口:

?
1
2
3
4
5
public JsonResult TokenBinderTest(TokenModel tokenModel)
{
  var output = "Id:" + tokenModel.Id + ",Name:" + tokenModel.Name + ",Description:" + tokenModel.Description;
  return Json(new ReturnModel_Common { msg = output });
}

調用下:

詳解ASP.NET MVC 常用擴展點:過濾器、模型綁定

可以看出,“1:汪杰:oppoic.cnblogs.com”已經被綁定到tokenModel這個對象里面了。但是如果稍復雜的模型綁定IModelBinder就無能為力了。

場景二、去除對象某個屬性的首位空格

?
1
2
3
4
5
6
7
8
public class Student
{
  public int Id { get; set; }
 
  public string Name { get; set; }
 
  public string Class { get; set; }
}

如果前端傳來的Name屬性有空格,如何去除呢?利用DefaultModelBinder即可實現更靈活的控制

?
1
2
3
4
5
6
7
8
9
10
11
12
public class TrimModelBinder : DefaultModelBinder
{
  protected override object GetPropertyValue(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor, IModelBinder propertyBinder)
  {
    var obj = base.GetPropertyValue(controllerContext, bindingContext, propertyDescriptor, propertyBinder);
    if (obj is string && propertyDescriptor.Attributes[typeof(TrimAttribute)] != null)//判斷是string類型且有[Trim]標記
    {
      return (obj as string).Trim();
    }
    return obj;
  }
}

標注下需要格式化首位屬性的實體:

?
1
2
3
4
5
6
7
8
9
10
[ModelBinder(typeof(TrimModelBinder))]
public class Student
{
  public int Id { get; set; }
 
  [Trim]
  public string Name { get; set; }
 
  public string Class { get; set; }
}

好了,測試下:

?
1
2
3
4
5
6
7
8
9
10
11
public JsonResult TrimBinderTest(Student student)
{
  if (string.IsNullOrEmpty(student.Name) || string.IsNullOrEmpty(student.Class))
  {
    return Json(new ReturnModel_Common { msg = "未找到參數" });
  }
  else
  {
    return Json(new ReturnModel_Common { msg = "Name:" + student.Name + ",長度:" + student.Name.Length + " Class:" + student.Class + ",長度:" + student.Class.Length });
  }
}

可見,標注了Trim屬性的Name長度是去除空格的長度:7,而沒有標注的Class屬性的長度則是6。

詳解ASP.NET MVC 常用擴展點:過濾器、模型綁定

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:http://www.cnblogs.com/oppoic/p/6407896.html?utm_source=tuicool&utm_medium=referral

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 午夜视频一区二区三区 | 一区二区日韩精品 | 亚洲视频自拍 | 精品伊人 | a免费在线 | h在线观看视频 | 欧美视频在线播放 | 亚洲国产精品一区二区三区 | 欧美高清成人 | av在线第一页 | 精品日韩视频 | 日韩成人精品在线 | www.天天操| 精品乱子伦一区二区三区 | 成人午夜网站 | 免费欧美| 欧美中文字幕在线 | 亚洲精品在线视频 | 亚洲国产精品久久久久久6q | 久久精品a一级国产免视看成人 | 国产视频网 | 国产精品 日韩 | 国产精品一区在线 | av手机在线电影 | 久久久国产一区 | 天堂免费在线 | 日韩精品在线观看视频 | 欧美日韩在线精品 | 国产精品久久久久久亚洲调教 | 日韩美女国产精品 | 久久蜜桃精品一区二区三区综合网 | 亚洲a在线观看 | 国产成人无遮挡在线视频 | 乱人伦xxxx国语对白 | 中文字幕欧美日韩 | 日韩精品一区二区在线视频 | 国产成人一级毛片 | 午夜网| 精品网站在线 | 久久色视频| 亚洲欧美自拍视频 |