Remove 'Try it out!' buttons from Swagger-ui

This is a quick way of removing the ‘try it out’ buttons from specific operation types, when using Swagger-ui for documentation

This will be a short one.
When using Swashbuckle to create documentation, you might want to remove the Try it out buttons, maybe all of them, or maybe just the ones on Put on Post operations
Well I’ve created a small script that is injected into swagger-ui through the SwaggerConfig.cs
The following script will remove the TryItOut buttons from all Put and Post operations.

The script is injected through the SwaggerConfig.cs like so

Remember that the .js file needs to be an Embedded Resource else it won’t work.

Adding basic authentication to swashbuckle

Note: This is applies to swashbuckle 5.2.2 and below, will update post for 5.4.0.


On my recent endeavors, I’ve had the pleasure of getting to use “Swagger”, yes it is as swag as it sounds…
Swagger for .Net is thankfully packaged by a guy I only know as “DomainDriven” on github.
The .Net version is called “Swashbuckle”.
I will not go in to adding swashbuckle to your project, the README pretty much says it all.
Lets get back to basic-auth.
According to the swashbuckle docs, to add Basic-Auth to swashbuckle, you need to add the following in the SwaggerConfig.cs file

This adds the “SecurityDefinition” as per the swagger spec.
The SwashBuckler docs finishes the security segment with

NOTE: These only define the schemes and need to be coupled with a corresponding “security” property at the document or operation level to indicate which schemes are required for each operation. To do this, you’ll need to implement a custom IDocumentFilter and/or IOperationFilter to set these properties according to your specific authorization implementation

Which is what I’ll be showing you how to do.

Onwards!

Lets start with the UI.
To remove the APIKey input and replace that with a nice username/password input pair, we need to inject a new index.html.
Note: You can see the base swagger index file here
You can see the entire index.html below
[/learn_more]
What I’ve changed from the original index.html is actually not a whole lot.
I’ve removed everything that had to do with the apikey input and instead added new username and password inputs;
Now all there needs to be done is to inject the new index file into swagger-ui

Now that we have the UI in order, we move on to the actual spec implementation.
To actually live up to the swagger spec, we are still missing the Security Requirement Object on the operations.
According to the spec;

Security Requirement Object
Lists the required security schemes to execute this operation. The object can have multiple security schemes declared in it which are all required (that is, there is a logical AND between the schemes).
The name used for each property MUST correspond to a security scheme declared in the Security Definitions.

Which basically means that we need to add "security": [{"basic": []}] to all of our operations.
This only applies to the code generated by swagger, but how do we implement this through Swashbuckle?
We need to create a class that inherits from the IOperationFilter interface.
And then add the security scheme to all operation.
The security theme is basically just a “basic : []” applied under the security configuration (speaking in pure swagger spec terms).

Now we just need to apply the OperationsFilter in the SwaggerConfig

and that is it, now the “basic” security scheme will be applied to all operations.

Global Pagination in WebAPI using ActionAttributeFilter

I like pagination, but only when it isn’t forced. In my perspective pagination should be opt-in not opt-out, so to speak.
Pagination should also, be easy to implement and not something we, as developers, should need to implement on a per entity basis.
The usual manual way to do this (also as described by the ASP.net docs) is adding pageSize and pageNumber as query-parameters on individual actions.

This is fine for smaller things, but not very DRY.
What I ended up doing was to create an ActionFilter.
With an ActionFilter you can “plug” 2 places,

  1. OnActionExecuted – which is before the request hits the method
  2. OnActionExecuting – which is after the request has hit the method.

ActionFilterExplanation
You can read about actionfilters here

Off to the code

So we need to create an ActionFilter, that will “plug” after the response has been attached to the HttpContext, where we look for specific query-parameters and then filter the response based on the query-parameters given.
Let’s list what we need to do.
1. Create a class that inherits from ActionFilterAttribute.
2. Look for specific query parameters.
3. Filter the response based on the query parameters.

1. Create a class that inherits from ActionFilterAttribute.

easy – we simply add a new class and inherit from ActionFilterAttribute and then override OnActionExecuted.

2. Look for specific query parameters.

Now, how do we get the query parameters? luckily the context object is full of good stuff!
context.Request.RequestUri.Query contains all of our queries and luckily there is a helper class to help us parse the query string.
using HttpUtility.ParseQueryString, we are able to .Get values based on the key (key-value pair)
So, to get, the value of “brand” from a request looking like the following http://myurl.com/cars?brand=hyundai

So for paging it would look something like this.

Note: I’m going the limit/offset route, instead of page/pagesize.
In the above we check for our specific query parameters (limit/offset) and set limit and offset accordingly

3. Filtering the response

Get the content from the response and Take & Skip the limit and offset (if needed).

4. Setting the newly filtered results as the “new” results of the request

Set the new result as the response content

5.

Now we just need to apply the filter to our entire project.
This happens in the WebApiConfig.cs file.

The full PagingFilter can be seen here


Now we never have to think about pagination support for specific actions, it’s already handled through our attribute.
Do note that this comes with a cost. – We are already loading the entire dataset into memory and then paginating it.
in production system, where performance is key – please use native DB paging support.