I have the following code
public class MyService : IMyService
{
private readonoly IUnitOfWork _unitOfWork;
public MyService(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
}
//This code is used by web client
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IMyService>().To<MyService>();
kernel.Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope();
}
I have a web and windows service client both use the "MyService" class. I want to dispose the "unit of work" at the end of HTTP request if the client is web, where as if the client is a windows service, I want to dispose the unit of work after every database call. how to achieve that? can I add an extra flag to the MyService constructor, to identify the client, but then how to modify the above code to pass a hardcoded value to that parameter when mapping the concrete types to the interfaces?
You will probably have some sort of MyServiceRunner in yourr Windows service that calls your MyService. This class is Windows service specific and this would be the place to explicitly control the lifetime of the IUnitOfWork. Or you can write a decorator for MyService that controls the unit of work.
A few things to note. Although you can reuse the IUnitOfWork on a per-web-request basis, DO NOT Commit the unit of work at the end of the web request, but explicitly do this after a service (succesfully) executed. Since the scope of your IUnitOfWork is very different in the Windows Service, you probably need some explicit code or explicit registration to handle this. However, make sure that your MyService is oblivious to this: It shouldn't need to care.
If you have many services that you want to call in the Windows Service, you might want to think about applying the command/handler pattern for handling business logic. You can read more about it here.
Related
is it Ok if we call wep api service inside web form using api dll. we will be hosting both api and application on same server and requiring internal calling.
It's not very clear what you are after.
First of all if you write an API of some kind then you have to call it to interact with it. There's no middle ground here. If you don't want to call anything then you don't need an API. The purpose of an API is to provide a way to interact with some data storage, so behind your controllers you'd have a layer which talks to a database for example, or even another API.
If you don't want to make any calls then why bother with an API at all? Write a class library, one or several, doing whatever you need them to do and interact with your database this way.
I worked in a project before where I had a somewhat similar situation and ended up writing class libraries which were then shared by a UI project and a WebApi project, so you could work with them either way. This worked quite well actually. If you are looking for something similar then that's what I would go with. Keep the stuff of interest separate so you can expose with an API call or a direct dll reference.
So assuming that your controller methods look something like this:
public interface IService
{
Task<Value> GetValueAsync(int id);
}
public class Service : IService
{
public Task<Value> GetValueAsync(int id)
{
//...
// Code to return a value
//...
}
}
public class ValueController : ApiController
{
private IService _service;
public ValueController(IService service)
{
_service = service
}
public Task<IHttpActionResult> GetValueAsync(int id)
{
return Ok(await _service.GetValueAsync(id));
}
}
Then it is perfectly okay to call the method in the Service class. I would not call the method in the controller as that will cause more problems than you probably want to deal with.
I am hosting WebApi controller inside a stateless service with one instance. The service instance (I mean the instance of the WebApiService class created by the SF runtime) maintains some transient state as member fields, exposing the state through internal (thread-safe) methods. The WebApi controller needs to call the methods to access that state.
WebApiService.cs:
-----------------
internal sealed class WebApiService : StatelessService
{
private int _state;
internal int GetState() { return this._state; }
ServiceController.cs:
---------------------
public class ServiceController : ApiController
{
public async Task<IHttpActionResult> GetStateAsync()
{
// Here I'd like to grab somehow the WebApiService instance
// and call its GetState internal method.
My questions are:
How can the controller get a reference to the WebApiService instance?
Is it safe to store the WebApiService instance in a static field (perhaps set in the WebAspiService constructor)?
Inject the service instance as a dependency to your controllers through a DI container.
Here's an example with Web API hosted on Katana using Unity. It's a stateful service but it works exactly the same way for a stateless service: https://github.com/Azure-Samples/service-fabric-dotnet-getting-started/tree/master/Services/WordCount/WordCount.Service
Here's an example using Asp.Net Core and its built-in dependency injection container (also stateful, but same thing applies): https://github.com/vturecek/service-fabric-xray/tree/master/src/xray.Data
I think you could use a DI container for that. I can recommend simpleinjector (but there are many that can do the same), simpleinjector has got object lifetime management also per request and a web api package. You could put your state instance in a container as a singleton and inject it in your controllers, that would be a thread safe way, better stay away from static fields in a multithreaded web environment.
You have to resolve the stateless service in your controller before you can call the methods of the stateless service:
public async Task<IHttpActionResult> GetStateAsync()
{
var proxyLocation = new ServiceUriBuilder("WebApiService");
var svc = ServiceProxy.Create<IWebApiService>(proxyLocation.ToUri());
return svc.GetState();
}
You need to create an interface IWebApiService that contains the GetState method. WebApiService needs to implement it. Basically you need to abstract WebApiService with the IWebApiService interface.
In normal ASP.MVC projects we configure the dependency resolver with Unity and the Unity.Mvc3 package from http://unitymvc3.codeplex.com/
We have this test service registered with a HierarchicalLifetimeManager
container.RegisterType<ITestService, TestService>(new HierarchicalLifetimeManager());
And we hook up the container with Mvc in Global.asax.cs:
System.Web.Mvc.DependencyResolver.SetResolver(new Unity.Mvc3.UnityDependencyResolver(container));
And we run this test controller:
public class TestController : Controller
{
private readonly ITestService _service;
public TestController(ITestService service)
{
this._service = service;
}
public ActionResult Test()
{
var locatedService = System.Web.Mvc.DependencyResolver.Current.GetService<ITestService>();
if (_service == locatedService)
return View("Success - Same Service");//This is always the result in an MVC controller
else
throw new Exception("Failure - Different Service Located");//This is never the result in an MVC controller
}
}
However, on this project we are adding a number of WebAPI controllers.
We have this configuration in global.asax.cs (using http://unitywebapi.codeplex.com/ for now. But I am open to suggestions):
System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
We have created an ApiTestController similar to TestController inheriting from ApiController rather than from Controller.
However, the ApiTestController fails its test. I understand that the System.Web.Mvc.DependencyResolver class and the System.Web.Mvc.DependencyResolver.Current property are specific to Mvc. But does WebAPI have an equivalent?
System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver.GetService does not work because the System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver instance is the parent container that I configured. It is not the child controller that was used to inject the ITestService into the constructor.
This user seems to have a similar problem: http://unitywebapi.codeplex.com/discussions/359413
But I feel that this probably has more to do with ASP.NET's WebAPI than it has to do with Unity.
Thanks
After looking over the source of http://unitymvc3.codeplex.com/ and http://unitywebapi.codeplex.com/ I created this class:
public class MyUnityDependencyResolver : Unity.Mvc3.UnityDependencyResolver, System.Web.Http.Dependencies.IDependencyResolver
{
public MyUnityDependencyResolver(IUnityContainer container)
: base(container)
{
}
public System.Web.Http.Dependencies.IDependencyScope BeginScope()
{
return this;
}
public void Dispose()
{
Unity.Mvc3.UnityDependencyResolver.DisposeOfChildContainer();
}
}
Configuration in gobal.asax.cs:
var myResolver = new MyUnityDependencyResolver(container);
System.Web.Mvc.DependencyResolver.SetResolver(myResolver);
System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver = myResolver;
Unity.Mvc3.UnityDependencyResolver uses HttpContext.Current.Items to manage child containers. MyUnityDependencyResolver may not be the most "correct" implementation of System.Web.Http.Dependencies.IDependencyResolver, but it seems to work so far.
I will mark this as the answer in a couple days if no one else has any better answers.
Unfortunately, when you call the GlobalConfiguration.Configuration.DependencyResolver.GetService, it completely ignores any scope and resolves using the outer non-child container which is around for the lifetime of the application. This is an issue with Web Api and makes it impossible to use constructor injection for per-request dependencies outside of controllers. Confusingly this is completely different behaviour from MVC as you say.
What you can do is use the GetDependencyScope() extension method off HttpRequestMessage. Anything you resolve using this will be in per request scope when using HierarchicalLifetimeManager in conjunction with Unity.WebApi. The request is available from action filters and handlers so may be a viable workaround.
Obviously this is pure service location rather than dependency injection which is far from ideal but I have not found another way to access per-request dependencies outside of controllers.
See this post for more info.
The DependencyResolver is not the right seam for dependency injection in ASP.NET WebAPI.
Mark Seemann has two really good posts on DI with WebAPI.
Dependency Injection and Lifetime Management with ASP.NET Web API
Dependency Injection in ASP.NET Web API with Castle Windsor
If you want to do it right you should have a look at them.
It seems like at least 90+% of the Controller Actions I am writing will need to access the database. To me it seems like a logical step to have the database context automatically injected.
I have never used dependency injection before so I want to confirm this is something that is a pattern. If it is, how should I go about doing this? I know ASP.NET MVC 3 has "improved dependency injection" support, but do I still need an external framework? If so what is the default and how do I configure it to create a new database context per http request?
ASP.NET MVC 3 doesn't have improved DI support - it has improved support for the Service Locator anti-pattern (go figure). Fortunately it has had support for DI since MVC 1 through the IControllerFactory interface.
To answer the question, however, yes, it sounds like a perfectly normal thing to inject a Repository into a Controller (although normally we would slide a Domain Model in between the two).
This is best done with Constructor Injection like this:
public class MyController
{
private readonly IMyRepository repository;
public MyController(IMyRepository repository)
{
if (repository == null)
{
throw new ArgumentNullException("repository");
}
this.repository = repository;
}
public ViewResult MyAction(int barId)
{
var bar = this.repository.SelectBar(barId);
return this.View(bar);
}
}
You'll need to provide a custom IControllerFactory to enable Constructor Injection with the MVC framework - the easiest thing is to derive from DefaultControllerFactory.
Once you have a custom IControllerFactory, you can register it in Global.asax like this:
ControllerBuilder.Current.SetControllerFactory(new MyControllerFactory());
This is a duplicate of another question, but copying from the other one:
I've run into an issue with Felix SCR where I get the message:
ServiceFactory.getService() resulted in a cycle
The reason this appers to be occuring is because within an activation method, call it ServiceAImpl (which provides ServiceA), the service registers another service, call it ServiceB.
I have another service component, call it ServiceCImpl, which depends on both ServiceA and ServiceB. By ServiceAImpl registering ServiceB, ServiceCImpl has become satisfied and within the same call to activate ServiceAImpl, the ServiceCImpl binding methods are called. When the binding method for ServiceA is called, the cycle is detected and the component fails to initialize.
Maybe there is a way to allow the SCR to wait to bind the ServiceCImpl or maybe I need to be registering ServiceB differently?
I guess what doesn't make sense is why the Felix SCR will activate ServiceCImpl within the activation method of ServiceAImpl. I wouldn't think that ServiceCImpl would be considered satisfied until after the activation method has exited. Perhaps this is an issue of using declarative services while still registering services directly with the framework?
Haven't tried other SCR implementations, like Equinox's version, but I might try that to see if there is a difference, but maybe somebody knows if this is a OSGi thing or a Felix thing?
Additional Info: As to why ServiceB is not a service component...ServiceA actually has a service reference of 0..n for another service, call it ServiceD. Everytime a ServiceD interface is provided by a component, a ServiceB is registered using the same service object. Normally the same provider of ServiceD could provide ServiceB, but the idea is to make the overall interface for developers more simplistic so they don't have to provide multiple service interfaces (also, ServiceB has some properties that are set automatically that would have to be done manually and possibly could be done incorrectly).
The reason this appears to be happening is that ServiceAImpl is a delayed component that has already been loaded so ServiceA is in fact already resgistered before the component is activated. However, when another component comes along that needs ServiceA, this causes ServiceAImpl to be activated. Part of the activation process of ServiceAImpl is to register ServiceB which immediately causes ServiceCImpl to be activated. A change was made in FELIX-2368 to immediately activate a component by making most SCR operations synchronous.
A workaround is to make ServiceAImpl an immediate component which isn't desired as it shouldn't be activated if nothing needs the service. In this case, the activation method is completed when the component is loaded and by the time it is needed and bound to another component there is no problem.
I've tried to recreate this scenario with a small set of test bundles and the ProSyst OSGi FW.
However, if I register a service with DS, I am not able to register an other service from within the activate() method. If I just use DS to obtain services, I can register services as usual. So there is probably really a problem with DS/SCR...
Example:
public class ServiceAImpl implements ServiceA, ServiceB, ManagedService {
public void activate(ComponentContext _context) {
_context.getBundleContext().registerService(
ManagedService.class.getName(),
this,
null);
_context.getBundleContext().registerService(
ServiceB.class.getName(),
this,
null);
}
#Override
public void doA() {
System.out.println("Doing A Stuff");
}
#Override
public void doB() {
System.out.println("Doing B Stuff");
}
#Override
public void updated(Dictionary arg0) throws ConfigurationException {
}
}
This class will register 2 Services (ServiceB, ManagedService) with this bnd. file:
Private-Package: org.test.impl
Service-Component: org.test.impl.ServiceAImpl
Bundle-Category: test
but only 1 service (ServiceA) with this sample:#
Private-Package: org.test.impl
Service-Component: org.test.impl.ServiceAImpl;provide:=org.test.ServiceA
Bundle-Category: test
So probably you should/have to try to register the services either via DS/SCR or the "classic way" via bundle context.