Asp.net-Mvc

當我有一個可為空的參數時,ModelState.IsValid 為 false

  • March 19, 2021

我重現了我在一個全新的 MVC Web API 項目中遇到的問題。

這是預設程式碼,稍作修改。

public string Get(int? id, int? something = null)
{
   var isValid = ModelState.IsValid;
   return "value";
}

如果你去http://localhost/api/values/5?something=123然後這工作正常,並且 isValid 是true.

如果你去http://localhost/api/values/5?something=那麼 isValid 是false

我遇到的問題是,如果您為可為空的項目提供空值或省略值,則 ModelState.IsValid 會標記驗證錯誤說"A value is required but was not present in the request."

ModelState 字典也如下所示:

在此處輸入圖像描述

有兩個條目something,一個可以為空,我不確定它是否重要。

知道如何解決此問題,以便在省略可空參數或提供為空參數時模型有效嗎?我在我的 web api 中使用模型驗證,如果每個帶有可為空參數的方法都生成模型錯誤,它會破壞它。

似乎預設綁定模型不能完全理解可為空的類型。從問題中可以看出,它給出了三個參數錯誤,而不是預期的兩個。

您可以使用自定義可為空的模型綁定器解決此問題:

模型粘合劑

public class NullableIntModelBinder : IModelBinder
{
   public bool BindModel(System.Web.Http.Controllers.HttpActionContext actionContext, ModelBindingContext bindingContext)
   {
       if (bindingContext.ModelType != typeof(int?))
       {
           return false;
       }

       ValueProviderResult val = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
       if (val == null)
       {
           return false;
       }

       string rawvalue = val.RawValue as string;

       // Not supplied : /test/5
       if (rawvalue == null)
       {
           bindingContext.Model = null;
           return true;
       }

       // Provided but with no value : /test/5?something=
       if (rawvalue == string.Empty)
       {
           bindingContext.Model = null;
           return true;
       }

       // Provided with a value : /test/5?something=1
       int result;
       if (int.TryParse(rawvalue, out result))
       {
           bindingContext.Model = result;
           return true;
       }

       bindingContext.ModelState.AddModelError(bindingContext.ModelName, "Cannot convert value to int");
       return false;
   }
}

用法

public ModelStateDictionary Get(
   int? id, 
   [ModelBinder(typeof(NullableIntModelBinder))]int? something = null)
{
   var isValid = ModelState.IsValid;

   return ModelState;
}

改編自asp.net頁面:http ://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api供進一步閱讀和替代方法將其設置在類(控制器)級別而不是每個參數。

這處理了 3 個有效場景:

/test/5
/test/5?something=
/test/5?something=2

這首先將“某物”設為空。其他任何東西(例如?something=x)都會出錯。

如果您將簽名更改為

int? somthing

(即 remove = null)然後您必須明確提供參數,即/test/5除非您也調整您的路線,否則它不會是有效路線。

引用自:https://stackoverflow.com/questions/32861365