Mocking HttpRequest in ASP.NET 4.0 - asp.net

I've seen a lot of similar threads but none that actually address my particular situation.
I'm writing unit tests in ASP.NET 4.0 web application (ASP.NET Forms, not MVC). There are several spots in the code where I call the ServerVariables collection to call variables like REMOTE_ADDR. Since my unit tests do not actually initiate HttpRequests when executing my code, things like ServerVariables are Null and therefore error when I try to call HttpContext.Current.Request.ServerVariables("REMOTE_ADDR")
All the solutions I've found to address this issue refer to MVC and so they assume that HttpRequest derives from HttpRequestBase, which it does in MVC but not in ASP.NET Forms.
I tried using Moq but you can't mock a sealed class, and HttpRequest is unfortunately sealed with no interface.

The HttpRequestBase and HttpRequestWrapper classes can be used with a bit of work.
Wherever you currently access HttpContext.Current.Request -- or just plain Page.Request -- you'll need to use an injectable instance of HttpRequestBase instead. Then you'll need to inject a different subclass of HttpRequestBase depending on whether you're testing or live.
For live code, you'd probably inject an HttpRequestWrapper instance that wraps HttpContext.Current.Request:
var liveRequest = new HttpRequestWrapper(HttpContext.Current.Request);
For test code, you'd need to create and inject your own mock subclass of HttpRequestBase. Presumably Moq can do that for you on-the-fly.

Related

Get same instance of a component registered with Autofac as InstancePerLifetimeScope in Global.asax methods as is injected into a controllers?

I have a situation where I need to manually instantiate some objects in Application_BeginRequest that are dependent on some of the same components that I've registered with Autofac. I'd like to use the same instances of components that I've registered with Autofac with InstancePerLifetimeScope for injection into my MVC and WebAPI controllers. My config for both MVC and Web API works as expected, and an example of a component registration looks like so:
builder.Register(c => new MyDbContext()).AsSelf().InstancePerLifetimeScope();
Now I want to use that same instance in the class I'm instantiating in Application_BeginRequest. I've tried the following methods:
//Tried with MVC controllers
DependencyResolver.Current.GetService<MyDbContext>()));
AutofacDependencyResolver.Current.ApplicationContainer.Resolve<MyDbContext>()));
AutofacDependencyResolver.Current.RequestLifetimeScope.Resolve<MyDbContext>()));
//Tried with Web API controllers
GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(MyDbContext))
But none give me what I'm looking for, even at later points in the request lifecylce (ie, beyond BeginRequest). As an aside, I need this to work with the Web API configuration, but I tried the first 3 methods just to see if I could get any of the resolved instances to match up with what Autofac is injecting.
I have what I believe is a decent understanding of lifetime scopes in Autofac and my assumption is that the instances that are being resolved for my application's controllers are in a child scope that the none of the above 4 methods are pointed towards, but it's fuzzy to me what each of the above methods is trying to do in regard to which scope they are looking at and how they decide. What's even fuzzier is what lifetime scopes Autofac is automatically creating for the components that are ultimately injected into my controllers and when they're created.
Clarification on the points above would be a big bonus, but my primary question here is how do I get Autofac to hand me the same instances of registered components in Global.asax that it resolves for Web API and MVC controllers?
If you read up on this subject, you'll notice that folks mention that in most circumstances for a web application, InstancePerLifetimeScope and InstancePerRequest can be used interchangeably. What they don't mention are the exceptions where these two registrations behave differently. Gerrod has an excellent article on lifetime scopes inside of ASP.NET MVC/Web API applications and how they work in which he elaborates on this piece of info that most omit. Understanding this difference is crucial to this scenario, and his article cleared up any misunderstandings I had in regards to InstancePerLifetimeScope registration in relation to ASP.NET applications. It also made me realize that, because I need to share instances of resolved components across my MVC/Web API controllers and within the global.asax, InstancePerLifetimeScope is no longer a suitable means of registration for this application- I now need to use InstancePerRequest.
As per the docs, InstancePerRequest actually uses InstancePerMatchingLifetimeScope under the hood. What I need is a reference to the child scope that is tagged with "AutofacWebRequest" that lives under the root scope. This is the scope that both my MVC and Web API controllers resolve their dependencies from, since they both use the same tag. So how do I get a reference to that particular scope? This was my solution, and I'd love to know if there's a better way to do it.
First off, I need to change my registration from
builder.Register(c => new MyDbContext()).AsSelf().InstancePerLifetimeScope();
to
builder.Register(c => new MyDbContext()).AsSelf().InstancePerRequest();
Now, after I've built my container I have the following method:
private void SetDependencyResolversForMvcAndWebApi(ILifetimeScope container)
{
container.ChildLifetimeScopeBeginning += CaptureRequestLifetimeScope;
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);
}
The only part that wasn't there before is the event subscription. Everytime my container creates a child scope, my event handler gets called. The event handler looks like this:
private void CaptureRequestLifetimeScope(object sender, LifetimeScopeBeginningEventArgs args)
{
if (args.LifetimeScope.Tag == MatchingScopeLifetimeTags.RequestLifetimeScopeTag)
{
//Get the ILifetimeScope created for components registered with InstancePerRequest
var requestScope = args.LifetimeScope;
//This is the same DbContext instance that will be injected into
//my WebAPI and MVC controllers
var context = requestScope.Resolve<MyDbContext>();
//do the rest of my stuff
}
}
I've tested this by holding onto a reference of the resolved DbContext that's resolved within the CaptureRequestLifetimeScope event handler and comparing it to the DbContext instances that are injected into my Web API and MVC controllers, and they are indeed pointing to the same object.
Well, I think you should try changing .InstancePerLifetimeScope() into .InstancePerRequest();
As Autofac says about InstancePerLifetimeScope:
When you resolve the instance per lifetime scope component, you get a single instance per nested scope (e.g., per unit of work).
So when you do Resolve<MyDbContext>() you are probably doing it in a different Lifetime scope than you controller (I guess it's because you're doing an explicit resolution); that's why you're getting a diffent instance.
InstancePerRequest instead:
Some application types naturally lend themselves to “request” type semantics, for example ASP.NET web forms and MVC applications. In these application types, it’s helpful to have the ability to have a sort of “singleton per request.”
The begin phase of your request is already in the request phase, so you shoud get the same instance there and inside your controllers.
Instance per request builds on top of instance per matching lifetime scope by providing a well-known lifetime scope tag, a registration convenience method, and integration for common application types.
Based on this, probably, you can also go for the .InstancePerMatchingLifetimeScope("myrequest"), but you will have to manually instanciate a Lifetime scope everywhere like this using(var scope1 = container.BeginLifetimeScope("myrequest")); I think is not so practical.
Obviously I suppose you will not use those elements outside of the request scope, or you will get an exception. In that case, you are forced to the MatchingLifetimeScope.
If you need more details, the Autofac guide is extremely clear.
DependencyResolver.Current.GetService<MyDbContext>()));
AutofacDependencyResolver.Current.RequestLifetimeScope.Resolve<MyDbContext>()));
are same. They get current request lifetime scope. If you resolve some instance here, it shares it with cotrollers. (In this stiuation, instance per request and instance per lifetime will be same. Because their lifetime is same).
AutofacDependencyResolver.Current.ApplicationContainer.Resolve<MyDbContext>()));
This wil be resolved from root container. That's why it will create another instance for request lifetime scope. This will not be shared. And this will live in root container. (If you have per request instance, this will give error).
I have tested first one. It shares instance resolved in Application_BeginRequest with mvc controllers but not with Api controllers.
Then I tried to get GlobalConfiguration.Configuration.DependencyResolver.GetRequestLifetimeScope() in Application_BeginRequest it returns null.
I think, if it's api request, Autofac doesn't start request lifetime yet in Application_BeginRequest (May be it's related .net).
So if it's api request and if we can't reach autofac request life time. I don't know how to share this instance with mvc and api controllers which is resolved in Application_BeginRequest.
May be Travis can make it clear.

null HttpContext inside SendAsync method of IIdentityMessageService

I have a piece very simple code that used to work before I tried upgrading to ASP.NET Identity. This is a real head-scratcher.
Using ASP.NET MVC 5 with ASP.NET Identity 2.1 (latest-and-greatest at the time of writing this post)
I have a "user forgot their email" controller action that does this:
await this.UserManager.SendEmailAsync(
user.Id,
AccountStrings.ForgotPasswordEmailTitle,
string.Format(AccountStrings.ForgotPasswordEmailMessage, callbackUrl));
My user manager uses an implementation of IIdentityMessageService to shoot out the email and my code is in Task SendAsync(IdentityMessage message). Inside that method I need an active Http context since I'm using the Razor view engine to construct the email. Again, this used to work, until today.
As of today, an exception is thrown inside my method as the email is being rendered telling me I have no active Http context. And sure thing, HttpContext.Current is null. It's not null when the SendEmailAsync is called inside the controller action, it's not null after the await in the task continuation, but it's null inside SendEmailAsync.
I'm using the correct <system.web><httpRuntime targetFramework="4.5.1" /></system.web>
flags inside web.config, everything is by the book. And now, after updating some component - whether it's a minor ASP.NET MVC version or ASP.NET Identity version - I don't know - HttpContext.Current is null.
I have an ugly "fix" where I save the HttpContext.Current to a local var as my IdentityMessageService is created and set the current HttpContext to that value while SendAsync is executing, which works, but this definitely smells like a pretty serious regression inside the ASP.NET stack, somewhere.
Has anyone encountered anything similar?
I have not encountered this exact problem, but my gut feeling say that HttpContext.Current should not be used inside SendEmailAsync and this is not a bug, but intentional implementation on the part of Identity framework. I'll guess that a completely new thread is created just to send out an email and this thread does not have access to HttpContext.Current, i.e. this thread does not depend on the Http request/response.
So my thought would be to decouple your email generation from HttpContext. And to help you do this there is a RazorEngine project that allows to work with Razor views, but without HttpContext. This project is available via nuget:
Install-Package RazorEngine
And judging by the documentation it is pretty easy to work with. I have never used it myself though, so can't go beyond what these web-pages are saying.

Using InjectionFactory to inject DbContext, lifetime of created instance

I have an ASP.NET MVC5 project with Unity as DI framework.
Consider the following code:
container.RegisterType<ApplicationDbContext>(
new InjectionFactory(c => new ApplicationDbContext()));
As my repositories are using the same DbContext, it would be practical to pass the same instance to all of them. However, every visitor of the site should have a separate instance of the context, not work on one big "site-wide" instance. I guess this reduces the possibilites to have an instance lifetime only for the current request.
As UnityConfig.RegisterComponents() is in the Application_Start() method, I guess it would only create one instance for the entire application.
What is the best practice in this case? I have thought about the following:
Create my own factory for the DbContext which returns a singleton, and inject this factory into my repositories
Move UnityConfig.RegisterComponents() to Application_BeginRequest()
I tried to search for InjectionFactory on Microsoft's site, not much luck (http://msdn.microsoft.com/en-us/library/microsoft.practices.unity.injectionfactory%28v=pandp.51%29.aspx)
What best practice should I follow in this case? I don't want to overengineer it, what is the simplest working solution?
I'm not a web developer but reading through the book Dependency Injection With Unity they did mention a special lifetime manager that you can use for a single HTTP request - PerRequestLifetimeManager
Perhaps that would work for your needs?
Remove the factory and replace with:
container.RegisterType<ApplicationDbContext>(new HierarchicalLifetimeManager());
This will result in an ApplicationDbContext instance per request and also take call of disposing of the context at the end of the request.
I think what you're after is the unit of work pattern.
Take a look at the following link
http://www.asp.net/mvc/tutorials/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application

Autofac lifetime scope issue with asp.net webforms

I'm having an issue with the lifetime scope of autofac lasting across a request in an asp.net webforms site.
I'm register a factory in auto fac thus:
builder.RegisterType<DoSomethingFactory>().As<IDoSomethingFactory>().InstancePerLifetimeScope();
This occurs in the app_start of course.
then I have a simple user control that calls a method of this factory
IDoSomethingFactory doSomethingFactory = Resolver.Resolve<IDoSomethingFactory>();
Number.Text = doSomethingFactory.DoSomething().ToString();
I have two instances of this control on a page, so that the DoSomething method should be called twice and the factory should be resolved twice also.
The first time I run the site, the contstructor for the DoSomethingFactory is fired, and there are 2 subsequent calls to the DoSomething method. The second request, results in 2 calls to the DoSomething method without a fresh new-ing up of the factory.
If I take out the InstancePerLifetimeScope on the registering then the factory is instantiated on each resolve. Most answers I have seen for this talk about an MVC site. I also have an MVC site and am using it in the same manner and it is working as requested, hence the need to question for asp.net webforms
To be clear I would like the factory to be instantiated once every request. Any help or ideas would be welcome.
Many thanks
Will
If you want to have one instance of your DoSomethingFactory per request you need to use the InstancePerHttpRequest extension method.
From the Autofac wiki: WebFormsIntegration
ASP.NET integration adds a special component lifetime that allows a component instance to live for the life of a single HTTP request. You can register components using the InstancePerHttpRequest() extension method in the Autofac.Integration.Web namespace.
So change your registration to:
builder.RegisterType<DoSomethingFactory>()
.As<IDoSomethingFactory>()
.InstancePerHttpRequest();

Accessing HttpContext in a class library - ASP.NET MVC

I am populating an instance of a class that represents the session variable and exists in a class library. I need to populate one property that requires me to get access to the Request object. I understand that I can use the System.Web.HttpContext.Current.Request to get the request object?
Is this a good practice. Something tells me that I should be doing this in the controller (or the base controller) that has the System.Web namespace.
Its not a bad practice - the object is available - if you design dictates to access it there - then by all means do it. One option is to pass in an instance of the request to the class's constructor if it makes you feel cleaner : )
According to Teemu Keiski on the ASP.NET forums:
You could use System.Web.HttpContext.Current but that's bad practise
since it makes your class library totally unusable outside web
applications (and if you access Sessions via that, it also gets
unusable for web services in most scenarios).
Anything you pass by getting straight HttpContext could be passed as
parameters into the class that needs it. And if you need to access
Response object directly, you could pass Response.OutputStream into
the class (which would take it as general Stream object)
Source: http://forums.asp.net/post/1311405.aspx
Fundamentally there's nothing wrong with this as long as you take a dependency on System.Web.Abstractions and pass into your class a reference to HttpRequestBase. The classes in this assembly are not sealed and all members are virtual which means your class will still be testable.
More info in the answers to the following SO question

Resources