0
votes

I have this url: /api/v1/books?status=1

status is an optional query parameter and my API controller looks like this.

class BookController : ApiController
{

   [HttpGet]
   public JsonResult GetBooks(Status status)
   {
         // return statement
   }
}

Status is an enum.

public enum Status
{
    None = 0,
    Available = 1,
    NotAvailable = 2,
    Modified = 3
    Deleted = 4
}

Controller accepts 0,1,2,3,4,5,6,7 values, but rejects 8,9,10,11,... values(returns 400 - Bad Request). For the value 5, the controller takes the enum as Available|Deleted (4+1=5) and for the 7(4+3) it takes Modified|Deleted. I want to reject the values that are not in the enum class. How can I handle this?

1
If you need bitwise operations on Enums, you must set each enum value to only use one single bit. Right now you could combine Available | NotAvailable and get 3, but 3 means Modified (I understand that Available | NotAvailable are mutually exclusive, but I am trying to make my point). So your values should be None = 0 (0b), Available = 1 (1b), NotAvailable = 2 (10b), Modified = 4 (100b) and Deleted = 8 (1000b). Now back to your question. Change the signature of the method to public JsonResult GetBooks(short status), then with code reject numeric values that represent invalid enum combinations. - JPortillo
Hi @needTobeanSRE,did you sitll have questions?If so,please follow up.If my answer help you,could you please accept as answer?Refer to:How to accept as answer. - Rena
@Rena Thank you for your answer. I got the point from your answer. Previously I have used [Flag] attribute on enum. So the controller accepts combinations of the enum. So I simply removed the [Flag] attribute and it worked. - needTobeanSRE

1 Answers

0
votes

You could add [Flags] attribute on your model.Then you could get the data like Available|Deleted.And add a custom action filter to reject 8,9,10,11... values:

Model:

[Flags]
public enum Status
{
    None = 0,
    Available = 1,
    NotAvailable = 2,
    Modified = 3,
    Deleted = 4      
}

Custom action filter:

public class ValidateModelAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        var url = actionContext.Request.RequestUri.Query;
        var list = url.Split('=');
        if (int.Parse(list[list.Length-1])>7)
        {
            actionContext.Response = actionContext.Request.CreateErrorResponse(
                HttpStatusCode.BadRequest,"the enum is invalid");
        }
    }
}

Register action filter in Global.asax:

public static void RegisterWebApiFilters(System.Web.Http.Filters.HttpFilterCollection filters)
{
    filters.Add(new ValidateModelAttribute());
}
protected void Application_Start()
{
    //other services...
    RegisterWebApiFilters(GlobalConfiguration.Configuration.Filters);
}

Result: enter image description here