具有默认值的Asp.net webapi枚举参数

我有一个控制器

[HttpGet] [RoutePrefix("api/products/{productId}")] public HttpResponseMessage Products(int productId,TypeEnum ptype=TypeEnum.Clothes) { if(!Enum.IsDefined(typeOf(TypeEnum),ptype)) //throw bad request exception else //continue processing } 

Myenum被宣布为

 public TypeEnum { Clothes, Toys, Electronics } 

目前,如果传递了一些垃圾值,它将被转换为默认值。 我想要做的是如果我将控制器称为api / products / 1,那么应该为ptype指定默认值即衣服。 如果我将控制器称为api / products / 1?pType = somegarbagevalue,那么控制器应抛出错误的请求exception。 我怎样才能做到这一点?

你必须使用string并使用TryParse()将字符串转换为Enum值。

 public HttpResponseMessage Products(int productId,string ptype="Clothes") { TypeEnum category = TypeEnum.Clothes; if(!Enum.TryParse(ptype, true, out category)) //throw bad request exception if you want. but it is fine to pass-through as default Cloathes value. else //continue processing } 

它可能看起来很幼稚,但这种方法的好处是允许ptype参数到任何字符串,并且当ptype无法绑定值时执行过程无exception。

将所有枚举参数定义为字符串,然后在任何地方解析它们意味着您必须在每个操作上执行此操作,并且您需要提出一致的方法,以便所有解析错误都符合。

这是一个参数绑定问题,不应该在控制器层中处理,应该在管道中处理。 一种方法是创建自定义filter并将其添加到您的配置中。

 public class ModelStateValidationAttribute : ActionFilterAttribute { public override void OnActionExecuting(HttpActionContext actionContext) { if (!actionContext.ModelState.IsValid) { actionContext.Response =  } } } 

在你的global.asax.cs中

 ... GlobalConfiguration.Configure(WebApiConfig.Register); ... public class WebApiConfig { public static void Register(HttpConfiguration config) { ... config.Filters.Add(new ModelStateValidationAttribute()); ... } } 

如果您遇到模型状态的问题,它的类型是ModelStateDictionary,您只需迭代它,然后它的Errors属性包含所有模型绑定问题。 例如

 modelState = actionContext.ModelState; modelState.ForEach(x => { var state = x.Value; if (state.Errors.Any()) { foreach (var error in state.Errors) {  } } });