Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Asp.net webapi enum parameter with default value

I have a controller

   [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 is declared as

public TypeEnum
{
  Clothes,
  Toys,
  Electronics
}

Currently if,some garbage value is passed it is getting converted into default value. What I want to do is if i call the controller as api/products/1 then the ptype should be assigned default value i.e clothes. If I call the controller as api/products/1?pType=somegarbagevalue then the controller should throw bad request exception. How can I achieve this?

like image 801
user3832953 Avatar asked Jul 13 '14 07:07

user3832953


2 Answers

Defining all your enum parameters as strings and then parsing them everywhere means you have to do this on every single action and you will need to come up with a consistent approach such that all parsing errors conform.

This is a parameter binding issue and should not be dealt with in the controller layer, it should be taken care of in the pipeline. One way to do this is to create a custom filter and add it to your config.

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

And in your global.asax.cs

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

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

If you're having trouble with the model state, it's type is a ModelStateDictionary and you simply iterate over it and then it's Errors property contains all the model binding issues. 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>
                }
            }
        });
like image 121
HeroicNonsense Avatar answered Oct 29 '22 10:10

HeroicNonsense


You have to do with string and use TryParse() to convert string to Enum value.

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
}

It may look naive but the benefit of this approach is to allow ptype parameter to whatever string and to perform process without exception when ptype fails to bind the value.

like image 23
Youngjae Avatar answered Oct 29 '22 11:10

Youngjae