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

时间:2014-07-13 07:10:35

标签: c# asp.net-web-api enums

我有一个控制器

   [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,则控制器应抛出错误的请求异常。我怎样才能做到这一点?

3 个答案:

答案 0 :(得分:14)

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

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

public class ModelStateValidationAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        if (!actionContext.ModelState.IsValid)
        {
            actionContext.Response = <your standardised error response>
        }
    }
}

在你的global.asax.cs

...
GlobalConfiguration.Configure(WebApiConfig.Register);
...

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

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

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

答案 1 :(得分:7)

您必须使用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无法绑定值时执行过程。

答案 2 :(得分:0)

这种类型的验证应在管道中而不是在控制器中处理。

    public abstract class ETagMatchAttribute : ParameterBindingAttribute
{
    private ETagMatch _match;

    public ETagMatchAttribute(ETagMatch match)
    {
        _match = match;
    }

    public override HttpParameterBinding GetBinding(HttpParameterDescriptor parameter)
    {
        if (parameter.ParameterType == typeof(ETag))
        {
            return new ETagParameterBinding(parameter, _match);
        }
        return parameter.BindAsError("Wrong parameter type");
    }
}

类似的东西。请参阅MSDN link了解详细说明