← Foundations path
.NETFoundations 31 / 37Asked by interviewers

Filter lifetime: ServiceFilter vs TypeFilter

“How do filters get services from DI, and what is the difference between ServiceFilter and TypeFilter?”

How you register a filter decides whether each request gets its own filter object or every request shares one.

See it

1/6 keeps the approver in a field, _approver. By type: one object per request.

In plain words

A filter is a class with code that MVC (ASP.NET Core's controller-based style of building web APIs) runs before or after a controller action (). A global filter applies to every action in the app. A filter is a class, so somebody must create its object. Who creates it, and how often, depends on how you register it. Four ways, three results. New object for each request: options.Filters.Add<AuditFilter>() (global, by type: MVC creates it, and DI fills its constructor) and [TypeFilter(typeof(AuditFilter))] (MVC creates a new one each time, no registration needed, DI only fills its constructor). Whatever you registered: [ServiceFilter(typeof(AuditFilter))] on a controller or action makes MVC ask the DI container for the filter, so you must register it (AddScoped<AuditFilter>() and so on). Scoped means one per request; singleton means one for the whole app. One object for every request: options.Filters.Add(new AuditFilter(...)) (you created one object yourself), or [ServiceFilter] with a singleton. Why it matters: a field in a shared filter is shared by every request running at that moment. If one request writes it and another reads it, data mixes. The code below shows that bug and the fix.

Say it in the interview

In the lending API

The four ways side by side, then the bug a shared filter causes. The filter stamps the approver on a response header, standing in for an audit row. Three files, each visited in turn (Program.cs registers, the controller picks, the filter file shows the bug), so the walk goes back to the first case in each. Tap Next line.

Diagram · step 1 keeps the approver in a field, _approver. By type: one object per request.
Program.cs · line 3 · 1 of 4By type: a new per request; DI fills its constructor.

What they ask next

Interviewers check that you can explain every line. Tap a question to open it.

Traps

Read more: Filters in ASP.NET Core: dependency injection