While working in the development of new APIs for the organization that I work for, it came up with a couple of requirements to validate the input that the API consumer was passing in the request.
There are several ways of doing this, but in the WebAPI world, something that is reusable was the focus here. For that, I used Action Filters and Parameter Bindings. Below I’m going to show how I implement both of them.
WebAPI Action Filter
In my first validation requirements, I would have to look into the body of the Http requests and validate that some of the fields being passed as a JSON.
To do so using an Action Filter we need to create a new class that derives from the ActionFilterAttribute class as below:
1 2 3 4 5 |
using System.Web.Http.Filter; public class MyValidationAttribute: ActionFilterAttribute { //... } |
In this class I wanted to be able to perform validations using regular expressions. I also wanted to add validations on the size of the strings in those Http JSON requests, so I updated the implementation to be as this:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public class MyValidationAttribute: ActionFilterAttribute { private readonly string _regEx; private readonly string _errorMsg; private int _maxLength; public MyValidationAttribute(string regEx, int maxLength, string errorMsg) { _regEx = regEx; _maxLength = mxaLength; _errorMsg = errorMsg; } } |
There one part missing here, but before going there, let me show how to apply this Action Filter in the WebAPI controller.
1 2 3 4 5 6 7 8 9 10 11 |
[MyValidation("[^a-zA-Z\-\d\s]", 18, "Only alphanumeric values are allowed")] public async Task<IHttpActionResult> Update([FromBody]MyClass myClass) { //... return StatusCode(HttpStatusCode.NoContent); } public class MyClass { public string MyValue { get; set; } } |
Now that I’m applying the attribute to the operation in the WebAPI controller, let’s complete the code to get the value from Http request and validate the information we want from it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public override void OnActionExecuting(HttpActionContext actionContext) { // Get MyClass Type object myClassTypeObj; actionContext.ActionArguments.TryGetValue("myClass", out myClassTypeObj); var myClass = (MyClass)myClassTypeObj; var match = Regex.Match(myClass.MyValue, _regEx) if (match.Success) { throw new HttpResponseException(HttpStatusCode.BadRequest); } } |
As you can see, this is a very powerful feature from WebAPI where we can implement common behaviors in our applications by applying Action Filters.
If you want to learn more about that, just go to the following Microsoft documentations about it:
https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/filters?view=aspnetcore-3.0
WebAPI HttpParameterBinding
The previous code, works well when we have an object being passed in the body of an Http request and you want to apply the Action Filter on the WebAPI controller operation. If you want to apply the same kind of validation, but on the individual parameters of the WebAPI controller operation, you need to work with Parameter Bindings.
To work with this structure you need to implement the following classes:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
public class MyParamValidationAttribute: ParameterBindingAttribute { private readonly string _regEx; private readonly string _errorMsg; public MyParamValidationAttribute(string regEx, string errorMsg) { _regEx = regEx; _errorMsg = errorMsg; } public override HttpParameterBinding GetBinding(HttpParameterDescriptor parameter) { new MyParamValidationParameterBinding(parameter, _regEx, _errorMsg); } } public class MyParamValidationParameterBinding: HttpParameterBinding, IValueProviderParameterBinding { private readonly string _regEx; private readonly string _errorMsg; public MyParamValidationParameterBinding(string regEx, string errorMsg) { _regEx = regEx; _errorMsg = errorMsg; } public override Task ExecuteBindingAsync(...) { //... var currentBoundValue = this.GetValue(actionContext); var m = Regex.Match(currentBoundValue, _regEx); if (m.Success) { thrown new HttpResponseException(HttoStatusCode.BadRequest); } } } |
The code above is not complete, but since I found this solution in StackFlow, here is the thread where you can get the full code and adapt to your scenarios.
Now, that the classes are implemented, you can apply them in your parameters as below:
1 2 3 4 5 |
public async Task<IHttpActionResult> Update([QueryStringValidation("[^a-zA-Z]", "Only letters are allowed")]string myValue) { //... return StatusCode(HttpStatusCode.NoContent); } |
Summary
For those that are working with WebAPI, using Action Filter and Parameter Bindings is a very powerful way of having common behavior shared among all your APIs.
1 thought on “Creating validation filters for WebAPI”