I've seen lots of code samples using an IoC Container with registrations such as:
// Autofac
builder.Register(c => new HttpContextWrapper(HttpContext.Current))
.As<HttpContextBase>()
.InstancePerRequest();
// Again Autofac
builder.RegisterModule(new AutofacWebTypesModule());
(see src for AutofacWebTypesModule HERE )
// Castle Windsor
container.Register(Component.For<HttpContextBase()
.LifeStyle.PerWebRequest
.UsingFactoryMethod(() => new HttpContextWrapper(HttpContext.Current)));
Together with controllers using contructor injection:
public class HomeController : Controller
{
private readonly HttpContextBase _httpContext;
public HomeController(HttpContextBase httpContext)
{
_httpContext = httpContext;
}
//....
}
Question 1:
Can you please explain the reason of wrapping HttpContextBase,HttpRequestBase and so on..?
Question 2:
What would be the difference between the Injected HttpContextBase vs HttpContext (Controller's property) vs System.Web.HttpContext.Current
Update
Question 3:
Which HttpContext to use in code, the Injected One or it is also good to call it through HttpContext and System.Web.HttpContext.Current? Are there any issues if calling both ways?
Answer 1
HttpContext is a notorious pain when it comes to testing, since it only exists in the context of a request. Since .net 3.5 HttpContextBase is an abstraction of HttpContext and lends itself to being injected through IOC frameworks
By letting the IOC container handle it you can register a different/deterministic instance be injected into your components at test time. In normal code you would inject the HttpContextWrapper that is the default implementation
From the linked page:
The HttpContextBase class is an abstract class that contains the same
members as the HttpContext class. The HttpContextBase class enables
you to create derived classes that are like the HttpContext class, but
that you can customize and that work outside the ASP.NET pipeline.
When you perform unit testing, you typically use a derived class to
implement members with customized behavior that fulfills the scenario
you are testing.
Answer 2
The injected HttpContextBase would return data that is needed in order for the test to succeed: a specific query string, a specific query, etc. Usually the injected implementation would only contain the needed methods for the test, ignoring all others, e.g the context .User.Identity.Name property in order to test authentication.
Answer 3
In code, you must always use the HttpContextBase that is injected, since you don't want to depend on a concrete implementation that may fail at test time. If calling both ways you may encounter problems, most notably in tests since the HttpContext.Current will return null.
Related
This issue is different, I know what DI is, but I want to know how asp.net core use DI. We can configure custom logging in ASP.NET Core, but I do not know why it works.
Normally, we use the new keyword to instantiate a class, and then we can use it in the controller. In ASP.NET Core, we use a controller constructor with parameter like below:
public class HomeController : Controller
{
private readonly ILogger _logger;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
}
}
I know it is a design pattern called Dependency Injection, but I am wondering how this is implemented. How did the ASP.NET Core team realize this?
In Dependency Injection and Inversion of Control jargon, what is injected is called a "service".
You register your services with an IoC container upon application startup, meaning: you tie concrete implementations and a lifetime to a certain type.
Now when a controller is required to serve an incoming request, MVC will use a controller factory to look up and instantiate the relevant controller. When that controller has constructor parameters, it'll ask the IoC container to resolve the required service parameters.
More information on learn.microsoft.com: Dependency injection into controllers.
I'm starting a new ASP.NET MVC project. In my last project, one of the biggest code smells was how I passed around the Entity Framework DbContext, stored it in HttpContext.Current, called SaveChanges() in my rendering event, and did all manner of (probably unseemly) related things.
Suppose that my unit of work always corresponds to a web request. What is the right way to create a DbContext, share that context to a business library (e.g. an assembly outside the MVC project responsible for processing some workflow activities), share result models back to my controller, and persist any changes?
I'll be honest, I don't know much about dependency injection. It sounds like it should be related, but I don't see how it would get me a shared context instance between my controller and my business processes in an external assembly.
If I only needed it from controllers, it would be easy. I'd stick to HttpContext. But now HttpContext has spilled over to my external library. Do I just define an interface that returns the current DbContext, and base an implementation of that on HttpContext?
Hope that's clear what I'm asking, as I'm a little lost.
Dependency injection definitely sounds like what you are after here. My preference is ninject so below is a bit of an example of how I do this with EF.
Install Ninject.MVC3 (available on nuget)
Go to \app_start\NinjectWebCommon.cs (added by the above package) and add the following to the RegisterServices method
kernel.Bind<MyContext>().ToSelf().InRequestScope(); //binding in the context in request scope, this will let us use it in our controllers
Inside a controller consume the context as follows
public class MyController : ....{
private readonly MyContext _context;
public MyController(MyContext context){ _context = context; }
//Do stuff with _context in your actions
}
This is a really simple example for you to try there are plenty of better ways to structure this as your application grows (such as ninject modules) but this will demonstrate how DI works.
A few things to note, Always make sure you bind the context in requestscope (or more frequently) as DBContext has a nasty habit of growing quite bit if it sticks around too long.
In terms of sharing it with your external stuff that can be injected too, eg
public class MyExternalLogic{
public MyExternalLogic(MyContext context){....}
}
public class MyController : ....{
private readonly MyContext _context;
public MyController(MyContext context, MyExternalLogic logic){ _context = context; ...}
//Do stuff with _context in your actions
}
In the above the same instance of DbContext will be used for both MyController and MyExternalLogic. Ninject will handle the creation of both objects.
There are also a bunch of other DI containers available which will give you very similar experiences. I highly recommend DI as it helps a lot with unit test-ability as well.
For some more examples of how I use Ninject to structure my MVC apps check out some of my projects on github, such as https://github.com/lukemcgregor/StaticVoid.Blog
I'm trying to get my head around how one would unit test an ASP.NET MVC project that accesses data through a repository of some sort.
During the unit tests I'd obviously want to create a mock repository but how do I pass this mock repository to the Controller instance being tested? Also how would the actual repository, that's really connected to a database, find its way to the controller?
Do I simply do this through the constructors as I've shown below? I think this is how I should set up my controllers, but I'd like some confirmation that this is correct:
public class SampleController : Controller
{
private IRepository _repo;
//Default constructor uses a real repository
// new ConcreteRepo() could also be replaced by some static
// GetRepository() method somewhere so it would be easy to modify
//which concrete IRepository is being used
public SampleController():this(new ConcreteRepo())
{
}
//Unit tests pass in mock repository here
public SampleController(IRepository repo)
{
_repo = repo;
}
}
As everyone has already said, you'll want to use an IoC* or DI** container. But what they haven't said is why this is the case.
The idea is that a DI container will let you bypass ASP.NET MVC's default controller-construction strategy of requiring a parameterless constructor. Thus, you can have your controllers explicitly state their dependencies (as interfaces preferably). How those interfaces map to concrete instances is then the business of the DI container, and is something you will configure in either Global.asax.cs (live) or your test fixture setup (for unit testing).
This means your controller doesn't need to know anything about concrete implementations of its dependencies, and thus we follow the Dependency Inversion Principle: "High-level modules should not depend on low-level modules. Both should depend on abstractions."
For example, if you were to use AutoFac, you would do this:
// In Global.asax.cs's Application_Start
using Autofac;
using Autofac.Integration.Mvc;
var builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.Register<IRepository>(() => new ConcreteRepo());
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
// In your unit test:
var controllerInstance = new SampleController(new InMemoryFakeRepo());
// In SampleController
public class SampleController : Controller
{
private readonly IRepository _repo;
public SampleController(IRepository repo)
{
_repo = repo;
}
// No parameterless constructor! This is good; no accidents waiting to happen!
// No dependency on any particular concrete repo! Excellent!
}
* IoC = inversion of control
** DI = dependency inversion
(the two terms are often used interchangeably, which is not really correct IMO)
Yeah, you're correct, you pass it to your constructor like you have it. By mocking IRepository your explicitly ensuring that the database dependent code doesn't get into the controller for testing, like you want.
When you actually run it, you'll want to setup your application to work with an inversion of control container to enable those dependencies to be injected into your controller (some popular ones are Ninject, StructureMap, and Windsor).
Here's a sample of testing using Moq:
private Mock<IRepository> _mockRepo;
private SampleController _controller;
[TestInit]
public void InitTest()
{
_mockRepo = new Mock<IRepository>();
_controller = new SampleController(_mockRepo.Object);
}
[Test]
public void Some_test()
{
_mockRepo.Setup(mr => mr.SomeRepoCall()).Returns(new ValidObject());
var result = _controller.SomeAction() as ViewResult;
Assert.IsNotNull(result);
}
Now you can test your actions and mock your IRepository to behave however you want.
The best answer I know is to use an Ioc Container:
http://www.hanselman.com/blog/ListOfNETDependencyInjectionContainersIOC.aspx
I prefer Castle Windsor
With the controller dependencies passed in you can then create mocks.
We have dependencies that implement interfaces which can be mocked.
For the real one, check out ninject mvc 3 on nuget, for unit testing I prefer to use fake objects with in-memory collections of known data
I'm working with some WebForms/MVC-agnostic tools, and I need to get an instance of HttpContext given a reference to an HttpContextBase object. I can't use HttpContext.Current because I need this to work asynchronously as well (HttpContext.Current returns null during an asynchronous request). I'm aware of HttpContextWrapper, but goes the wrong way.
The simplest way is to get the application, ApplicationInstance, and use its Context property:
// httpContextBase is of type HttpContextBase
HttpContext context = httpContextBase.ApplicationInstance.Context;
(thanks to Ishmael Smyrnow who noted this in the comments)
Original answer:
You can, especially if the HttpContextBase instance you've been handed is of type HttpContextWrapper at run-time. The following example illustrates how you can do this. It supposes you have a method called Foo that accepts context as HttpContextBase but then needs to call a method in a third-party assembly (that you may not have the good fortune to modify) that is expecting the context to be typed as HttpContext.
void Foo(HttpContextBase context)
{
var app = (HttpApplication) context.GetService(typeof(HttpApplication));
ThirdParty.Bar.Baz(app.Context);
}
// Somewhere in assembly and namespace ThirdParty,
// in a class called Bar, there is Baz expecting HttpContext:
static void Baz(HttpContext context) { /* ... */ }
HttpContextBase has a method called GetService as a result of supporting IServiceProvider. The GetService override of HttpContextWrapper delegates to the GetService implementation of the wrapped HttpContext instance. The GetService implementation of HttpContext allows you to query for usual suspects like HttpApplication, HttpRequest, HttpResponse and so on. It just so happens that HttpApplication has a property called Context and which returns an instance of HttpContext. So one gets at the wrapped HttpContext instance by asking HttpContextBase for HttpApplication via GetService followed by reading the Context property of the returned HttpApplication instance.
Unlike HttpContextBase, GetService does not appear as a public member of HttpContext but that is because HttpContext implements IServiceProvider.GetService explicity while HttpContextBase doesn't.
Bear in mind that Foo is no longer testable because it relies on being able to unwrap the underlying HttpContext during testing and which is next to impossible to fake/stub in the first place. The point of this answer, however, is to address the question, “How do I get an HttpContext object from HttpContextBase?”, literally. The illustrated technique is useful in those situations where you find yourself sandwiched between components you don't necessarily have the luxury to modify.
You can,
var abstractContext = new System.Web.HttpContextWrapper(System.Web.HttpContext.Current);
You can't.
The whole purpose of HttpContextBase is to abstract away the dependency on the concrete HttpContext class. While it may contain a concrete HttpContext (such as is the case with httpContextWrapper), other implementations may have absolutely nothing to do with HttpContext.
Your best option is to define a custom Abstract Factory that can get a HttpContextBase for you, since you can always wrap a concrete HttpContext in a HttpContextWrapper.
I'm designing medium-size website using asp.net mvc technology.
All business logic is organized into IServices (like IDomainService, IUserService, IAuthService, ITrainingService). All services are using IRepositories.
I'm using Ninject 1.5 to wire services with controllers and it seems working perfectly.
There is so far one subject I have no idea how to handle. Some services create contexts (per request) - for instance IDomainService creates DomainContext (per request) which is needed for IUserService.
ITrainingService is used only in TrainingController, which is accessible only by authorized users, and ITrainingService requires UserContext (also per request) to know who is having training.
This is my first project using IoC container.
Is there any design pattern or code-schema how to solve it?
I think I can fill context object using ActionFilters but how to manage their lifetime and where to put them to be accessible for IServices? (in an ellegant way)
I've used Ninject specifically in an MVC application. The way you'd accomplish this with Ninject is in the configuration or binding of your dependencies. When you do this, you specify how you want your object lifetimes to be managed. In most cases of a web app, you objects will be per request as you've indicated in your question.
One thing I've noticed in your question is that your DomainContext is being created by an IDomainService object and is used by other objects. If the domain service object is a sort of factory for a DomainContext, then you don't have much of a problem -- this becomes an exercise of how you configure Ninject to provide concrete objects and inject dependencies.
Here's general guidance on how you would structure your application -- bear in mind I don't have full understanding of your interfaces and classes:
public class GlobalApplication : NinjectHttpApplication {
protected override void RegisterRoutes(RouteCollection routes) {
// Your normal route registration goes here ...
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" }
);
}
// This function is resposible for creating a Ninject kernel. This is where
// the magic starts to happen.
protected override IKernel CreateKernel() {
var modules = new IModule[] {
new AutoWiringModule(),
new AutoControllerModule(
Assembly.GetExecutingAssembly()),
new ServiceModule()
};
return new StandardKernel(modules);
}
}
Note above that the easiest way to get Ninject to work is to derive your application class from the NinjectHttpApplication class. You will need to change your RegisterRoutes to an override method and will also be required to implement a method called CreateKernel. The CreateKernel method is responsible for returning the Ninject kernel which is itself the IoC container.
In the CreateKernel method, the Ninject-provided AutoControllerModule scans assemblies for MVC controller classes and registers them with the container. What this means is that dependencies on those controllers can now be injected by Ninject as it has become the controller provider for the application. The ServiceModule class is one that you need to create to register all of your services with Ninject. I'm guessing it would look something like this:
internal class ServiceModule : StandardModule {
public override void Load() {
Bind<IDomainService>()
.To<MyDomainService>()
.Using<OnePerRequestBehavior>();
Bind<DomainContext>()
.ToMethod( ctx => ctx.Kernel.Get<IDomainService>().CurrentDomainContext )
.Using<OnePerRequestBehavior>();
Bind<IService>()
.To<MyServiceType>()
.Using<OnePerRequestBehavior>();
}
}
Ninject's got a pretty expressive fluent interface for configuration. Note above that each statement basically associates a concrete class with an interface it implements. The "Using" phrase in the statement indicates to the Ninject kernel that the object will live for the life of the request only. So, for example, this means that anytime an IDomainService object is requested from the Ninject kernel during the same request, the same object will be returned.
As for you context objects, I'm taking a stab that your domain service creates these contexts and acts as a factory of sorts. In that regard, I bound instances DomainContext classes above to be produced by getting the value of the a property called CurrentDomainContext off the IDomainService. That's what the lambda above accomplishes. The nice thing about the "ToMethod" binding in Ninject is that you have access to a Ninject activation context object that allows you to resolve objects using the kernel. That's exactly what we do in order to get the current domain context.
The next steps are to ensure your objects accept dependencies properly. For example, you say that ITrainingService is used only in the TrainingController class. So, in that case I would ensure that TrainingController has a constructor that accepts an ITrainingService parameter. In that constructor, you can save the reference to the ITrainingService in a member variable. As in:
public class TrainingController : Controller {
private readonly ITrainingService trainingService;
public TrainingController(ITrainingService trainingService) {
this.trainingService = trainingService;
}
// ... rest of controller implementation ...
}
Remember that Ninject has already registered all of your controllers with the Ninject kernel, so when this controller is created and it's actions are invoked, you'll have a reference to the ITrainingService by way of the trainingService member variable.
Hope this helps you out. Using IoC containers can become quite confusing at times. Note, I highly recommend you check out the Ninject documentation -- it's a very well written introduction to Ninject as well as DI/IoC concepts. I've also left out discussion of the AutoWiringModule shown above; however, Nate Kohari (Ninject's creator) has a good write-up on his blog about this feature.
Good luck!
Im not exactly sure if I understand your problem completely, hopefully this bit of advice can help.
When using an IoC container you let the container handle object lifetime managment. I have only used Castle Windsor and StructureMap for dependency injection so I cant give you a concrete example for how to do this with Ninject.
Looking through the Ninject documentation I think you want to look at Activation Behaviours to specify object lifetime management.
Hope this helps.