Alexey Strakh Alexey Strakh - 10 months ago 97
ASP.NET (C#) Question

Optional attribute in web API routing

I'm using web api filter to validate all incoming view models and return view state error if it's null:

public class ValidateViewModelAttribute : ActionFilterAttribute
public override void OnActionExecuting(HttpActionContext actionContext)
if(actionContext.ActionArguments != null)
foreach (var argument in actionContext.ActionArguments)
if (argument.Value != null)

var argumentBinding = actionContext.ActionDescriptor?.ActionBinding.ParameterBindings
.FirstOrDefault(pb => pb.Descriptor.ParameterName == argument.Key);

if(argumentBinding?.Descriptor?.IsOptional ?? true)

actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, string.Format("Arguments value for {0} cannot be null", argument.Key));

if (actionContext.ModelState.IsValid == false)
actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, actionContext.ModelState);

I have web api working in production and now I got new request to add one optional parameter to one action. Optional.... to keep api compatibility

public async Task<IHttpActionResult> ApplyOrder(int orderId, [FromBody] ApplyOrderViewModel input = null)

and if I don't specify input
= null
it isn't considered to be an optional parameters and couldn't pass my validation. With
= null
I'm getting the following error:

"Message": "An error has occurred.", "ExceptionMessage": "Optional
parameter 'input' is not supported by 'FormatterParameterBinding'.",

"ExceptionType": "System.InvalidOperationException", "StackTrace": "
at System.Web.Http.Controllers.HttpActionBinding.ExecuteBindingAsync(

How can I keep my global viewmodel validation in place and still mark this only method parameter to be optional.

  • ps: I cannot use syntax route with
    sign because it's [FromBody]

  • pss: I wouldn't like to introduce v2 api because it isn't a v2 api,
    I'm adding new optional parameter

  • psss: I need some kind of attribute
    to update binding descriptor and specify that my parameter is
    optional, then it'll pass my validation.

Answer Source

Since it is your own validation that it cannot pass without = null you can add a custom [OptionalParameter] attribute and check for it existence e.g., though you need to do some caching by type to avoid excessive use of Reflection.

Second option is to have some Base class for all of your optional parameters like below and just check with is operator.

public abstract class OptionalParameter

Third option is to do the same with an interface.

Though the attribute is the cleanest in my opinion it's a bit harder to implement.