user3832953
user3832953

Reputation: 113

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?

Upvotes: 11

Views: 19326

Answers (3)

Taran
Taran

Reputation: 3221

This type of validation should be handled in pipeline not in controller.

    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");
    }
}

something like this. refer to MSDN link for detailed explanation

Upvotes: 0

HeroicNonsense
HeroicNonsense

Reputation: 141

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>
                }
            }
        });

Upvotes: 14

Youngjae
Youngjae

Reputation: 25050

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.

Upvotes: 7

Related Questions