3

I like to have static helper classes in my apps for common plumbing stuff, like checking roles, or Razor Html helpers and stuff... but how do you do this in the DI world?

Like lets say I want an extension helper to check if a user is an admin

public static async Task<bool> IsAdmin(this ApplicationUser user)
...
if(user.IsAdmin()){...}

So pre-core I could just ignore DI and create a UserManager all inside IsAdmin do whatever I need to do. But now is there no way to get the UserManager in these helpers to just use? The only way I can see is to inject it into the Controller, then pass along into the method (which I find ugly). Then there's the issue of trying to do user.IsAdmin() in the Razor view, would I need to add the UserManager to the ViewData collection to get it into the view markup?

Am I just missing something here?

Thanks, Steve

Steve McNiven-Scott
  • 1,770
  • 2
  • 15
  • 29

2 Answers2

1

Well you are talking about a cross-cutting concern here and one way how I've seen cross cutting concerns solved in ASP.NET Core MVC is with attributes (like [Authorize] for example). Which I think is an elegant solution.

So, if I understand your question correctly I think you can solve this with an Action Filter. Damien Bod described a few days ago how to use ActionFilters: https://damienbod.com/2016/09/09/asp-net-core-action-arguments-validation-using-an-actionfilter/.

So in short, you inherit from ActionFilterAttribute and make your own curstom filter called MyCustomFilter or whatever. Have this MyCustomFilter request UserManager in its constructor via DI. Then above any action method in a controller you say:

ServiceFilter[typeof(MyCustomFilter)]

And in MyCustomFilter you ofcourse have logic to check if User is IsAdmin and then take action accordingly.

Now, I've always used Microsoft's Unity to handle cross cutting concerns via interception (you can read more about that here: https://dannyvanderkraan.wordpress.com/2015/09/30/real-world-example-of-adding-auditing-with-dependency-injections-interception/. But last time I checked there is no Unity container for asp.net core yet. But this guy has a great article about porting it to core: https://dzimchuk.net/post/bring-your-own-di-container-to-aspnet-5-unity. I would really like my Interception back! Very elegant solution to cross cutting concerns. They are working on it though: https://github.com/unitycontainer/unity/issues/66. Fingers crossed...

Danny van der Kraan
  • 5,344
  • 6
  • 31
  • 41
1

First of all if you just asked how to use static class with di, i would say that your question is duplicate of How to use DI inside a static Method in Asp.net Core rc1

But as i see, you have some other question?

But now is there no way to get the UserManager in these helpers to just use?

Yes there is a way : Service Locator pattern. But it is an anti pattern (see this article) . As far as possible you should avoid to use this pattern. Also see discussion in github.

The only way I can see is to inject it into the Controller, then pass along into the method (which I find ugly)

I think this way is better than you want. I would prefer this.

Then there's the issue of trying to do user.IsAdmin() in the Razor view, would I need to add the UserManager to the ViewData collection to get it into the view markup?

In Aspnet core you can inject a dependency into a view, so you don't need to use ViewData. Simply you can inject UserManager into your view and then pass it as parameter to method. Take a look at official docs

Community
  • 1
  • 1
adem caglin
  • 22,700
  • 10
  • 58
  • 78