簡體   English   中英

禁用Asp.Net MVC中的模型驗證

[英]Disable Model Validation in Asp.Net MVC

如何在Controller中禁用單個Action的模型驗證? 或者我可以通過在啟動時注冊模型類型來為每個模型執行此操作嗎?

我希望ModelBinder綁定到模型,但之后它不應該執行模型驗證。

我不希望驗證發生的原因是因為我試圖將邏輯從控制器移動到服務層,該服務層將負責驗證模型,因為我不能假設傳遞給服務的模型包含有效數據。

據我所知,這是推薦的方法(在控制器中沒有邏輯),所以我覺得有點奇怪,我似乎無法找到任何關於如何禁用模型驗證(每個動作或每個模型類型)。

請注意,我不想禁用整個Web應用程序的模型驗證(通過刪除驗證提供程序),並且我不想禁用檢查發布的惡意代碼的輸入驗證。


UPDATE

我正在使用.Net 4.0和MVC 3預覽1

在檢查模型是否有效之前,只需刪除不需要的項目

ModelState.Remove("Email");
if (ModelState.IsValid)
{
   // your logic
}

我用這段代碼解決了這個問題:

public ActionResult Totals(MyModel model)
{
    ModelState.Clear();
    return View(model);
}

不確定這是正確的方式。

遺憾的是,除了使用特定的ModelBinder注冊您不想驗證的每個模型類型(包括嵌套復雜類型)之外,似乎沒有簡單的方法來禁用ModelBinder中發生的模型驗證。 可以使用以下代碼完成:

ModelBinders.Binders[typeof(MyModelType)] = new NonValidatingModelBinder();

創建一個可以附加到操作方法或操作方法參數的SkipValidationAttribute似乎不可能,因為它應該在ControllerActionInvoker中實現,但是沒有辦法讓ModelBinder知道它應該在SetProperty()中進行任何驗證。在GetParameterValue()方法中調用BindModel()時的OnModelUpdated方法。

我建議您在兩個地方執行驗證,而不是嘗試在UI中關閉驗證。 我理解您的觀點,即服務不能假定它正在傳遞有效數據 - 這是一個有效的問題,也是您的服務應該進行驗證的原因。 但是您應該在UI中進行驗證。 這也很好,因為您可以進行客戶端驗證以防止用戶錯誤並為您提供更好的體驗。

我絕對不喜歡2.0版本中的這個添加,因為正如您在問題中所述,驗證在服務層中更有意義。 通過這種方式,您可以在其他非Web應用程序中重用它,並且無需模擬自動驗證機制就可以更輕松地對其進行測試。

Controller層中的驗證毫無意義,因為在這部分中,您只能驗證模型數據而不是業務規則。 例如,考慮一個負責添加新評論的服務和一個想要發布新評論的用戶,他/她發布的評論中的數據可能是有效的,但如果用戶由於行為不當而被禁止發表評論會發生什么?在過去? 您應該在服務層中進行一些驗證,以確保不會發生這種情況,如果發生這種情況,則拋出異常。 簡而言之,必須在服務層中進行驗證。

我使用xVal作為我的驗證框架,因為它與DataAnnotationModel兼容,允許我在任何地方放置驗證並執行客戶端驗證而不需要額外的努力,甚至是遠程客戶端。 這是我在每個服務開始時使用它的方式,例如登錄服務:

public void SignIn(Login login) {
    var loginErrors = DataAnnotationsValidationRunner.GetErrors(login);

    // Model validation: Empty fields?
    if (loginErrors.Any())
        throw new RulesException(loginErrors);

    // Business validation: Does the user exist? Is the password correct?
    var user = this._userRepository.GetUserByEmail(login.Email);

    if (user == null || user.Password != login.Password)

        throw new RulesException(null, "Username or password invalids");

    // Other login stuff...
}

簡單,獨立於網絡,簡單...然后,在控制器中:

public RedirectResult Login(Login login) {

    // Login the user

    try {

        this._authenticationRepository.SignIn(login);

    } catch (RulesException e) {

        e.AddModelStateErrors(base.ModelState, "Login");

    }

    // Redirect

    if (base.ModelState.IsValid)
        return base.Redirect(base.Url.Action("Home"));
    else return base.Redirect(base.Url.Action("Login"));
}

我知道這已經得到了回答,但你真正需要的是擴展DataAnnotationsValidatorProvider並覆蓋GetValidators方法。

然后,在啟動時,您將從ModelValidatorProviders.Providers刪除DataAnnotationsValidatorProvider並添加新的。

毋庸置疑,如果您根本不想進行任何驗證,只需讓GetValidators方法返回一個空集合即可。

在我的情況下,我需要在提交表單時刪除驗證,同時仍然保持客戶端驗證,因此以下內容:

public class DynamicModelValidatorProvider : DataAnnotationsModelValidatorProvider
{
   GetValidators(ModelMetadata metadata, ControllerContext context, IEnumerable<Attribute> attributes)
    {
        if (context.HttpContext.Request.HttpMethod == "POST")
        {
            return new ModelValidator[] { };
        }

        return base.GetValidators(metadata, context, attributes);
    }
}

我用[ValidateInput(false)]

不確定這是否會阻止模型驗證,還是僅阻止IIS提交驗證。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM