我使用ModelState.IsValid
验证输入:
[HttpGet]
[Route("subjects")]
[ValidateAttribute]
public IHttpActionResult GetSubjects(bool? isActive = null)
{
//get subjects
}
如果我传入uri ~/subjects/?isActive=abcdef
,我会收到错误消息:
价值' abcdef'对Nullable`1无效。
如果输入参数不可为空
public IHttpActionResult GetSubjects(bool isActive){
//get subjects
}
我收到错误消息:
价值' abcdef'对布尔值无效。
我想覆盖消息,如果是可空类型,那么我可以维护消息("值' abcdef'对布尔值无效。")。我怎么能这样做,因为在ModelState
错误中我没有获得数据类型。我将验证作为自定义ActionFilterAttribute
(ValidationAttribute
)实施。
答案 0 :(得分:2)
您可以更改格式化类型转换错误消息的回调。例如,我们将其定义为Global.asax.cs
:
public class WebApiApplication : HttpApplication
{
protected void Application_Start()
{
ModelBinderConfig.TypeConversionErrorMessageProvider = this.NullableAwareTypeConversionErrorMessageProvider;
// rest of your initialization code
}
private string NullableAwareTypeConversionErrorMessageProvider(HttpActionContext actionContext, ModelMetadata modelMetadata, object incomingValue)
{
var target = modelMetadata.PropertyName;
if (target == null)
{
var type = Nullable.GetUnderlyingType(modelMetadata.ModelType) ?? modelMetadata.ModelType;
target = type.Name;
}
return string.Format("The value '{0}' is not valid for {1}", incomingValue, target);
}
}
对于不可为空的类型Nullable.GetUnderlyingType
将返回null,在这种情况下,我们将使用原始类型。
很遗憾,您无法访问默认字符串资源,如果您需要本地化错误消息,则必须自行完成。
另一种方法是实现您自己的IModelBinder
,但这对您的特定问题不是一个好主意。
答案 1 :(得分:0)
Lorond的回答强调了asp.net web api在让程序员定制API的许多部分方面的灵活性。当我查看这个问题时,我的思考过程是在动作过滤器中处理它而不是覆盖配置中的某些内容。
public class ValidateTypeAttribute : ActionFilterAttribute
{
public ValidateTypeAttribute() { }
public override void OnActionExecuting(HttpActionContext actionContext)
{
string somebool = actionContext.Request.GetQueryNameValuePairs().Where(x => x.Key.ToString() == "somebool").Select(x => x.Value).FirstOrDefault();
bool outBool;
//do something if somebool is empty string
if (!bool.TryParse(somebool, out outBool))
{
HttpResponseMessage response = new HttpResponseMessage(System.Net.HttpStatusCode.BadRequest);
response.ReasonPhrase = "The value " + somebool + " is not valid for Boolean.";
actionContext.Response = response;
}
else
{
base.OnActionExecuting(actionContext);
}
}
然后使用动作过滤器属性
装饰控制器中的动作方法