Had issues with an implementation of filters in an ASP Core application, so I made a small test application to check how different filters behave. Below is my source and my findings.
- CustomAuthorisationFilterAttribute is an ActionFilterAttribute, the simplest implementation of a filter which does not allow dependencies injected
- CustomTypeFilterAttribute is TypeFilterAttribute, a more complex filter which allows dependency injection
- CustomApplicationFilter is a filter which uses an extension to add custom middleware to the request chain on demand. It allows dependencies but causes problems with exceptions which occur in the action, masking the stack trace and making it look like all exceptions occur in the middleware
Basic finding are that you should not use custom middleware as filters, since it causes side effects in exception handling in your application.
I’ve been working in ASP.MVC recently after working in Java for a long time. One of the things that struck me was the common use of session data in web application.
Now I know that people can and do use abuse sessions in Java, but the default routing and ease of access make using it more tempting in ASP.MVC. The standard routing convention of “/Controller/Action/:id” means you need to explicitly code to use RESTful paths that give you multiple IDs in URLs like “order/2/item/3” for non-trivial scenarios, and out of the box convenience methods like “TempData” seem to offer magical persistence between requests. These incentives combine to make using session data the path of least resistance in ASP.MVC.
Any data stored in session is inherently unreliable and use of it makes load balancing and scaling your application much more difficult. Once you use it, each instance of your web application must be able to find the users session data to reliably handle requests. Since it’s now extremely common to use multiple instances even for small applications (irresponsible not to for disaster recovery and redundancy) you will need to think about this before you deploy into production.
It also adds hidden complexity to testing your application. Each endpoint which relies on state stored in session needs to be tested with that application state simulated. This means you have at least two places in your code defining and using the same semi-structured data, which makes your tests complex/fragile and your code harder to maintain.
Once you make using session data part of your architecture it’s very hard to refactor and remove it. That little innocent use of TempData to store details from the last request will spread as Developers think “If it was ok there then it’s ok here…” and “one more can’t hurt” (the broken windows theory). Now your user flows in the web application rely on session stored details to go from screen A to B to C, and refactoring them means re-writing and testing a lot of the view/controller logic to replace the data held in session.
There are acceptable uses for session data in web application, authentication is the obivous one. What they have in common is having alternative flows to cope if session data is not found without breaking functionality.
If you have an over reliance of session in your application you are making a flakey, hard to scale and maintain application that will at best limp into production. At worst it will fall over and take your users data with it.
There are common patterns and methods to avoid needing session data, below are some links to help: