Using ASP.NET Web API. Is there a way to automatically return a status code 400 if a parameter is null? I found this question but that is a global solution that is applied to all methods, I want to do this on a per method per parameter basis.
So, for example, this is what I am currently doing:
public HttpResponseMessage SomeMethod(SomeNullableParameter parameter) { if (parameter == null) throw new HttpResponseException(HttpStatusCode.BadRequest); // Otherwise do more stuff. }
I would really just like to do something like this (notice the required attribute):
public HttpResponseMessage SomeMethod([Required] SomeNullableParameter parameter) { // Do stuff. }
Both URI and Query Parameters are mandatory by default.
Optional Parameters in Web API Attribute Routing and Default Values: You can make a URI parameter as optional by adding a question mark (“?”) to the route parameter. If you make a route parameter as optional then you must specify a default value by using parameter = value for the method parameter.
Web APIs allow businesses to access 3rd-party data and seamlessly integrate it anywhere and anytime it's required, offering unmatched data processing efficiencies and cost savings. APIs have transformed the way businesses interact with each other and the way they provide value to their customers.
Binding is a process to set values for the parameters when Web API calls a controller action method. Web API methods with the different types of the parameters and how to customize the binding process.
Passing Data in your API Calls REST API endpoints can pass data within their requests through 4 types of parameters: Header, Path, Query String, or in the Request Body.
The approach I ended up using was to create a custom filter that I registered globally. The filter checks all request parameters for the RequiredAttribute
. If the attribute is found then it checks if the parameter was passed with the request (not null) and returns status code 400 if it was null. I also added a cache to the filter to store the required parameters for each request to avoid the reflection hit on future calls. I was pleasantly surprised to find that this works for value types as well since the action context stores the parameters as objects.
EDIT - Updated solution based on tecfield's comment
public class RequiredParametersFilter : ActionFilterAttribute { // Cache used to store the required parameters for each request based on the // request's http method and local path. private readonly ConcurrentDictionary<Tuple<HttpMethod, string>, List<string>> _Cache = new ConcurrentDictionary<Tuple<HttpMethod, string>, List<string>>(); public override void OnActionExecuting(HttpActionContext actionContext) { // Get the request's required parameters. List<string> requiredParameters = this.GetRequiredParameters(actionContext); // If the required parameters are valid then continue with the request. // Otherwise, return status code 400. if(this.ValidateParameters(actionContext, requiredParameters)) { base.OnActionExecuting(actionContext); } else { throw new HttpResponseException(HttpStatusCode.BadRequest); } } private bool ValidateParameters(HttpActionContext actionContext, List<string> requiredParameters) { // If the list of required parameters is null or containst no parameters // then there is nothing to validate. // Return true. if (requiredParameters == null || requiredParameters.Count == 0) { return true; } // Attempt to find at least one required parameter that is null. bool hasNullParameter = actionContext .ActionArguments .Any(a => requiredParameters.Contains(a.Key) && a.Value == null); // If a null required paramter was found then return false. // Otherwise, return true. return !hasNullParameter; } private List<string> GetRequiredParameters(HttpActionContext actionContext) { // Instantiate a list of strings to store the required parameters. List<string> result = null; // Instantiate a tuple using the request's http method and the local path. // This will be used to add/lookup the required parameters in the cache. Tuple<HttpMethod, string> request = new Tuple<HttpMethod, string>( actionContext.Request.Method, actionContext.Request.RequestUri.LocalPath); // Attempt to find the required parameters in the cache. if (!this._Cache.TryGetValue(request, out result)) { // If the required parameters were not found in the cache then get all // parameters decorated with the 'RequiredAttribute' from the action context. result = actionContext .ActionDescriptor .GetParameters() .Where(p => p.GetCustomAttributes<RequiredAttribute>().Any()) .Select(p => p.ParameterName) .ToList(); // Add the required parameters to the cache. this._Cache.TryAdd(request, result); } // Return the required parameters. return result; } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With