搜尋
首頁後端開發C#.Net教程ASP.NET MVC後台參數驗證的幾種方式

前言

參數驗證是一個常見的問題,無論是前端或後台,都需對使用者輸入進行驗證,以此來確保系統資料的正確性。對於web來說,有些人可能理所當然的想在前端驗證就行了,但這樣是非常錯誤的做法,前端代碼對於用戶來說是透明的,稍微有點技術的人就可以繞過這個驗證,直接提交數據到後台。無論是前端網頁提交的接口,還是提供給外部的接口,參數驗證隨處可見,也是必不可少的。總之,一切用戶的輸入都是不可信的。

參數驗證有許多種方式進行,以下以mvc為例,列舉幾個常見的驗證方式,假設有一個使用者註冊方法

[HttpPost]
public ActionResult Register(RegisterInfo info)

   

一、透過if-if

逐一對參數進行驗證,這種方式最粗暴,但當時在WebForm下也確實這麼用過。對於參數少的方法還好,如果參數一多,就要寫n多的if-if,相當繁瑣,更重要的是這部分判斷沒辦法重用,另一個方法又是這樣判斷。

二、透過 DataAnnotation

mvc提供了DataAnnotation對Action的Model進行驗證,說到底DataAnnotation就是一系列繼承了ValidationAttribute的特性,例如RangeAttribute,RequiredAttribute等等。 ValidationAttribute 的虛方法IsValid 就是用來判斷被標記的物件是否符合目前規則。 asp.net mvc在進行model binding的時候,會透過反射,取得標記的ValidationAttribute,然後呼叫IsValid 來判斷目前參數是否符合規則,如果驗證不通過,還會收集錯誤訊息,這也是為什麼我們可以在Action裡透過ModelState.IsValid判斷Model驗證是否通過,透過ModelState來取得驗證失敗資訊的原因。例如上面的例子:

if(string.IsNullOrEmpty(info.UserName))
 
{
 
  return FailJson("用户名不能为空");
 
}
 
if(string.IsNullOrEmpty(info.Password))
 
{
 
  return FailJson("用户密码不能为空")
 
}

   

事實上在webform上也可以參考mvc的實作原理來實現這個過程。這種方式的優點的實現起來非常優雅,而且靈活,如果有多個Action共用一個Model參數的話,只要在一個地方寫就夠了,關鍵是它讓我們的程式碼看起來非常簡潔。

不過這種方式也有缺點,通常我們的項目可能會有很多的接口,比如幾十個接口,有些接口只有兩三個參數,為每個接口定義一個類包裝參數有點奢侈,而且實際上為這個類別命名也是非常頭痛的一件事。

三、DataAnnotation 也可以標記在參數上

透過驗證特性的AttributeUsage可以看到,它不僅可以標記在屬性和欄位上,也可以標記在參數上。也就是說,我們也可以這樣寫:

public class RegisterInfo
 
{
 
  [Required(ErrorMessage="用户名不能为空")]
 
  public string UserName{get;set;}
 
 [Required(ErrorMessage="密码不能为空")]
 
  public string Password { get; set; }
 
}

   

這樣寫也是ok的,不過很明顯,這樣寫很方法參數會難看,特別是在有多個參數,或者參數有多種驗證規則的時候。

四、自訂ValidateAttribute

我們知道可以利用過濾器在mvc的Action執行前做一些處理,例如身份驗證,授權處理的。同理,這裡也可以用來驗證參數。 FilterAttribute是一個常見的過濾器,它允許我們在Action執行前後做一些操作,這裡我們要做的就是在Action前驗證參數,如果驗證不通過,就不再執行下去了。

定義一個BaseValidateAttribute基類如下:

public ActionResult Register([Required(ErrorMessage="用户名不能为空")]string userName, [Required(ErrorMessage="密码不能为空")]string password)

   

HandleError 用於在驗證失敗時處理結果,這裡ValidateHandlerProviders提過IValidateHandler。 IValidateHandler定義如下:

public class BaseValidateAttribute : FilterAttribute
 
{
 
  protected virtual void HandleError(ActionExecutingContext context)
 
  {
 
    for (int i = ValidateHandlerProviders.Handlers.Count; i > 0; i--)
 
    {
 
      ValidateHandlerProviders.Handlers[i - 1].Handle(context);
 
      if (context.Result != null)
 
      {
 
        break;
 
      }
 
    }
 
  }
 
}

   

ValidateHandlerProviders定義如下,它有一個預設的處理器。

public interface IValidateHandler
 
{
 
  void Handle(ActionExecutingContext context);
 
}

   

這樣做的目的是,由於我們可能有很多特定的ValidateAttribute,可以把這模組獨立開來,而把最終的處理過程交給外部決定,例如我們在專案中可以定義一個處理器:

public class ValidateHandlerProviders
 
{
 
  public static List<IValidateHandler> Handlers { get; private set; }
 
  
 
  static ValidateHandlerProviders()
 
  {
 
    Handlers = new List<IValidateHandler>()
 
    {
 
      new DefaultValidateHandler()
 
    };
 
  }
 
  
 
  public static void Register(IValidateHandler handler)
 
  {
 
    Handlers.Add(handler);
 
  }
 
}  

   

然後再應用程式啟動時註冊:ValidateHandlerProviders.Handlers.Add(new StanderValidateHandler());

舉個兩個子:🜎

ValidateRegexAttribute:

public class StanderValidateHandler : IValidateHandler
 
{
 
  public void Handle(ActionExecutingContext filterContext)
 
  {
 
    filterContext.Result = new StanderJsonResult()
 
    {
 
      Result = FastStatnderResult.Fail("参数验证失败", 555)
 
    };
 
  }
 
}

   

更多的驗證同理實現即可。

這樣,我們上面的寫法就變成:

public class ValidateNullAttribute : BaseValidateAttribute, IActionFilter
 
{
 
  public bool ValidateEmpty { get; set; }
 
  
 
  public string Parameter { get; set; }
 
  
 
  public ValidateNullAttribute(string parameter, bool validateEmpty = false)
 
  {
 
    ValidateEmpty = validateEmpty;
 
    Parameter = parameter;
 
  }
 
  
 
  public void OnActionExecuting(ActionExecutingContext filterContext)
 
  {
 
    string[] validates = Parameter.Split(&#39;,&#39;);
 
    foreach (var p in validates)
 
    {
 
      string value = filterContext.HttpContext.Request[p];
 
      if(ValidateEmpty)
 
      {
 
        if (string.IsNullOrEmpty(value))
 
        {
 
          base.HandleError(filterContext);
 
        }
 
      }
 
      else
 
      {
 
        if (value == null)
 
        {
 
          base.HandleError(filterContext);
 
        }
 
      }
 
    }
 
  }
 
  
 
  public void OnActionExecuted(ActionExecutedContext filterContext)
 
  {
 
  
 
  }
 
}

   

綜合看起來,還是ok的,與上面的DataAnnotation可以權衡選擇使用,這裡我們可以擴展更多有用的信息,如錯誤描述等等。

總結

當然每種方式都有缺點,這個是視具體情況選擇了。一般參數太多建議就用一個物件包裝了。

更多ASP.NET MVC後台參數驗證的幾種方式相關文章請關注PHP中文網!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
char數組在C語言中如何使用char數組在C語言中如何使用Apr 03, 2025 pm 03:24 PM

char 數組在 C 語言中存儲字符序列,聲明為 char array_name[size]。訪問元素通過下標運算符,元素以空終止符 '\0' 結尾,用於表示字符串終點。 C 語言提供多種字符串操作函數,如 strlen()、strcpy()、strcat() 和 strcmp()。

char在C語言中如何處理特殊字符char在C語言中如何處理特殊字符Apr 03, 2025 pm 03:18 PM

C語言中通過轉義序列處理特殊字符,如:\n表示換行符。 \t表示製表符。使用轉義序列或字符常量表示特殊字符,如char c = '\n'。注意,反斜杠需要轉義兩次。不同平台和編譯器可能有不同的轉義序列,請查閱文檔。

char在C語言字符串中的作用是什麼char在C語言字符串中的作用是什麼Apr 03, 2025 pm 03:15 PM

在 C 語言中,char 類型在字符串中用於:1. 存儲單個字符;2. 使用數組表示字符串並以 null 終止符結束;3. 通過字符串操作函數進行操作;4. 從鍵盤讀取或輸出字符串。

C語言各種符號的使用方法C語言各種符號的使用方法Apr 03, 2025 pm 04:48 PM

C 語言中符號的使用方法涵蓋算術、賦值、條件、邏輯、位運算符等。算術運算符用於基本數學運算,賦值運算符用於賦值和加減乘除賦值,條件運算符用於根據條件執行不同操作,邏輯運算符用於邏輯操作,位運算符用於位級操作,特殊常量用於表示空指針、文件結束標記和非數字值。

c#多線程和異步的區別c#多線程和異步的區別Apr 03, 2025 pm 02:57 PM

多線程和異步的區別在於,多線程同時執行多個線程,而異步在不阻塞當前線程的情況下執行操作。多線程用於計算密集型任務,而異步用於用戶交互操作。多線程的優勢是提高計算性能,異步的優勢是不阻塞 UI 線程。選擇多線程還是異步取決於任務性質:計算密集型任務使用多線程,與外部資源交互且需要保持 UI 響應的任務使用異步。

char在C語言中如何進行類型轉換char在C語言中如何進行類型轉換Apr 03, 2025 pm 03:21 PM

在 C 語言中,char 類型轉換可以通過:強制類型轉換:使用強制類型轉換符將一種類型的數據直接轉換為另一種類型。自動類型轉換:當一種類型的數據可以容納另一種類型的值時,編譯器自動進行轉換。

C語言 sum 的作用是什麼?C語言 sum 的作用是什麼?Apr 03, 2025 pm 02:21 PM

C語言中沒有內置求和函數,需自行編寫。可通過遍歷數組並累加元素實現求和:循環版本:使用for循環和數組長度計算求和。指針版本:使用指針指向數組元素,通過自增指針遍歷高效求和。動態分配數組版本:動態分配數組並自行管理內存,確保釋放已分配內存以防止內存洩漏。

避免 C語言 switch 語句中 default 引起的錯誤避免 C語言 switch 語句中 default 引起的錯誤Apr 03, 2025 pm 03:45 PM

避免 C 語言 switch 語句中 default 引發的錯誤的策略:使用枚舉代替常量,限制 case 語句的值為枚舉的有效成員。在最後一個 case 語句中使用 fallthrough,讓程序繼續執行以下代碼。對於沒有 fallthrough 的 switch 語句,始終添加一個 default 語句進行錯誤處理或提供默認行為。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

Atom編輯器mac版下載

Atom編輯器mac版下載

最受歡迎的的開源編輯器

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強大的PHP整合開發環境

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

VSCode Windows 64位元 下載

VSCode Windows 64位元 下載

微軟推出的免費、功能強大的一款IDE編輯器