In my current Asp.Net application I am finding a number core services that are slowly spreading throughout the application through the use of Dependency Injection. One of those services is the need to know who the current authenticated user is. I have a UserService that encapsulates the logic for getting the CurrentUser, but it seems like I am injecting this same service almost everywhere in my application. Is there a different method I could be using for accessing this Global service without constantly growing my constructors to inject yet another object into my classes? (of course I still want to maintain testability)
Related
My team maintains a very large .Net Core 2.1 web site. Lots of controllers, lots of services that get injected into the controllers via constructor injection.
Sometimes due to developer error a service class is no longer added to the DI container during startup. Obviously this leads to an exception when MVC tries to construct a controller that relies on that service (in response to an incoming request).
Problem is that this may affect only some lightly used controller, so our (far from perfect) regression testing doesn't pick up the regression bug. But it is still bound to be picked up by one of our (very demanding) customers.
I though of writing a unit test that would
Instantiate a ServiceCollection class (that implements IServiceCollection);
Call our own method that adds all services to that service collection (the same method used during normal startup);
Find all controllers through reflection, and try to construct them the same way MVC does - by getting dependent services from the DI container.
So my question is:
Does this approach make sense?
Is there an example somewhere that I could use?
Failing an example, how would I achieve 1) and 3) ?
I'm creating a new application in Zend Framework 3 and i have a question about a design pattern
Without entering in much details this application will have several Services, as in, will be connecting to external APIs and even in multiple databases, the workflow is also very complex, a single will action can have multiple flows depending on several external information (wich user logged in, configs, etc).
I know about dependency injections and Zend Framework 3 Service Manager, however i am worried about instanciating sereval services when the flow will actually use only a few of them in certain cases, also we will have services depending on other services aswell, for this, i was thinking about using singletons.
Is singleton really a solution here? I was looking a way to user singletons in Zend Framework 3 and haven't figured out a easy way since i can't find a way to user the Service Manager inside a service, as I can't retrive the instance of the Service Manager outside of the Factory system.
What is an easy way to implement singletons in Zend Framework 3?
Why use singletons?
You don't need to worry about too many services in your service manager since they are started only when you get them from the service manager.
Also don't use the service manager inside another class except a factory. In ZF3 it's removed from the controllers for a reason. One of them is testability. If all services are inject with a factory, you can easily write tests. Also if you read your code next year, you can easily see what dependencies are needed inside a class.
If you find there are too many services being injected inside a class which are not always needed you can:
Use the ProxyManager. This lazy loads a service but doesn't start it until a method is called.
Split the service: Move some parts from a service into a new service. e.g. You don't need to place everything in an UserService. You can also have an UserRegisterService, UserEmailService, UserAuthService and UserNotificationsService.
In stead of ZF3, you can also think about zend-expressive. Without getting into too much detail, it is a lightweight middleware framework. You can use middleware to detect what is needed for a request and route to the required action to process the request. Something like this can probably also done in ZF3 but maybe someone else can explain how to do it there.
Problem:
I am building a four layer system with Ui, ServiceLayer, BizLayer and DataLayer. In line with good practice the ServiceLayer hides the BizLayer and DataLayer from the Ui, and of course the ServiceLayer doesn't know what the Ui Layer is.
My implementation is a single .NET application with each layer in its own assembly. I am using Autofac.MVC3 in my MVC3 Ui layer to do all the resolving classes used in a web request. I also include standard Autofac in my ServiceLayer so that it can handle the registration of all other layers in my application. At system startup I call a method to register all the types with Autofac. This does:
Register the lower levels by calling a module inside the ServiceLayer. That handles the registration of itself and all other assemblies using the standard NuGet Autofac package.
Then the Ui layer uses the NuGet Autofac.MVC package to register the various controllers and the IActionInvoker for Action Method injection.
My UnitOfWork class in my DataLayer is currently registered with InstancePerLifetimeScope because it is registered by the ServiceLayer which uses plain Autofac and knows nothing about InstancePerHttpRequest. However I read here that I should use InstancePerHttpRequest scope.
Question:
My question is, can I pass a lifetime scope around, i.e. could the MVC layer pass the InstancePerHttpRequest down to the service layer to use where needed? Alex Meyer-Gleaves seemed to suggest this was possible in his comment from this post below:
It is also possible to pass your own ILifetimeScopeProvider implementation to the AutofacDependencyResolver so that you can control the creation of lifetime scopes outside of the ASP.NET runtime
However the way he suggests seems to be MVC specific as ILifetimeScopeProvider is a MVC extension class. Can anyone suggest another way or is InstancePerLifetimeScope OK?
InstancePerHttpRequestScope is in fact a variant of InstantPerLifetimeScope. The first one only works in a request. If you want to execute some stuff on a background thread, it won't be available.
Like you I'm using autofac in as.net mvc and multiple app layers. I pass around the Container itself for the cases where I need to have a lifetime scope. I have a background queue which executes tasks. Each taks pretty much needs to have its own scope and to be exdecuted in a transaction. The Queue has an instance of IContainer (which is a singleton) and for every task, it begins a new scope and executes the task.
Db access and all are setup as INstancePerLifetimeScope in order to work in this case and I don't have aproblem when I use them in a controller.
With the help of MikeSW, Cecil Philips and Travis Illig (thanks guys) I have been put on the right track. My reading of the various posts, especially Alex Meyer-Gleaves post here, it seems that InstancePerLifetimeScope is treated as InstancePerHttpRequest when resolved by the Autofac.MVC package, within certain limitations (read Alex's post for what those limitations they). Alex's comment is:
Using InstancePerHttpRequest ensures that the service is resolved from the correct lifetime scope at runtime. In the case of MVC this is always the special HTTP request lifetime scope.
This means that I can safely register anything that needs a single instance for the whole htpp request as InstancePerLifetimeScope and it will work fine as long as I don't have child scoped items. That is fine and I can work with that.
I have a WCF service application (actually, it uses WCF Web API preview 5) that intercepts each request and extracts several header values passed from the client. The idea is that the 'interceptor' will extract these values and setup a ClientContext object that is then globally available within the application for the duration of the request. The server is stateless, so the context is per-call.
My problem is that the application uses IoC (Unity) for dependency injection so there is no use of singleton's, etc. Any class that needs to use the context receives it via DI.
So, how do I 'dynamically' create a new context object for each request and make sure that it is used by the container for the duration of that request? I also need to be sure that it is completely thread-safe in that each request is truly using the correct instance.
UPDATE
So I realize as I look into the suggestions below that part of my problem is encapsulation. The idea is that the interface used for the context (IClientContext) contains only read-only properties so that the rest of the application code doesn't have the ability to make changes. (And in a team development environment, if the code allows it, someone will inevitably do it.)
As a result, in my message handler that intercepts the request, I can get an instance of the type implementing the interface from the container but I can't make use of it. I still want to only expose a read-only interface to all other code but need a way to set the property values. Any ideas?
I'm considering implementing two interfaces, one that provides read-only access and one that allows me to initialize the instance. Or casting the resolved object to a type that allows me to set the values. Unfortunately, this isn't fool-proof either but unless someone has a better idea, it might be the best I can do.
Read Andrew Oakley's Blog on WCF specific lifetime managers. He creates a UnityOperationContextLifetimeManager:
we came up with the idea to build a Unity lifetime manager tied to
WCF's OperationContext. That way, our container objects would live
only for the lifetime of the request...
Configure your context class with that lifetime manager and then just resolve it. It should give you an "operation singleton".
Sounds like you need a Unity LifetimeManager. See this SO question or this MSDN article.
If you have a decent layered ASP.NET MVC 3 web application with a data service class pumping out view models pulled from a repository, sending JSON to an Ajax client,
[taking a breath]
what's a good way to add data filtering based on ASP.NET logins and roles without really messing up our data service class with these concerns?
We have a repository that kicks out Entity Framework 4.1 POCOs which accepts Lambda Expressions for where clauses (or specification objects.)
The data service class creates query objects (like IQueryable) then returns them with .ToList() in the return statement.
I'm thinking maybe a specification that handles security roles passed to the data service class, or somehow essentially injecting a Lambda Expression in just the right place in the data service class?
I am sure there is a fairly standardized pattern to implement something like this. Links to examples or books on the subject would be most appreciated.
If you've got a single-tiered application (as in, your web layer and service/data layer all run in the same process) then it's common to use a custom principal to achieve what you want.
You can use a custom principal to store extra data about a user (have a watch of this: http://www.asp.net/security/videos/use-custom-principal-objects), but the trick is to set this custom principal into the current thread's principal also, by doing Thread.CurrentPrincipal = myPrincipal
This effectively means that you can get access to your user/role information from deep into your service layer without creating extra parameters on your methods (which is bad design). You can do this by querying Thread.CurrentPrincipal and cast it to your own implementation.
If your service/data layer exists in a different process (perhaps you're using web services) then you can still pass your user information separately from your method calls, by passing custom data headers along with the service request and leave this kind of data out of your method calls.
Edit: to relate back to your querying of data, obviously any queries you write which are influence by some aspect of the currently logged-in user or their role can be picked up by looking at the data in your custom principal, but without passing special data through your method calls.
Hopefully this at least points you in the right direction.
It is not clear from your question if you are using DI, as you mentioned you have your layers split up properly I am presuming so, then again this should be possible without DI I think...
Create an interface called IUserSession or something similar, Implement that inside your asp.net mvc application, the interface can contain something like GetUser(); from this info I am sure you can filter data inside your middle tier, otherwise you can simply use this IUserSession inside your web application and do the filtering inside that tier...
See: https://gist.github.com/1042173