How do access the HttpServerUtility in a WebAPI controller (MVC 4) - asp.net-mvc-4

I need to access the Server.MapPath(virtualPath) method in a controller in an MVC 4 ApiController.
The answer is usually to access it from ControllerContext.HttpContext.Server. However, unlike MvcControllers, the ControlerContext for an ApiController has no HttpContext.
The WebApiAppication that is instantiated in Global.asax.cs has an HttpContext element (Context). However, unlike MVC 3 and earlier, I can't find a way to access the WebApiApplication from a controller. (Earlier generations stored a reference to it in a static Instance variable. MVC 4 removes that.)
Also, I'm trying to find something that will also work without a ton of extra scaffolding when I call the controller methods from a unit Test. I think I could access it, even in a WebApi Controller, using HttpContext.Current (at least it compiles), but I can't mock that for testing. (I'm talking unit testing here, where you call directly to the Controller methods. I've seen some recent tutorials where you unit test with a thin HttpClient, and thus test the whole stack. That seems more like low-level integration testing to me.)
This doesn't seem like it should be that difficult, but I've spent several hours googling it and trying things, and my head's getting bloody from beating it against the wall.

I'd recommend you abstracting this functionality:
public interface IMyDependency
{
string MapPath(string path);
}
and then have an implementation:
public class MyConcreteDependency: IMyDependency
{
public string MapPath(string path)
{
return HostingEnvironment.MapPath(path);
}
}
and finally your ApiController is completely independent on all static method calls making it unit test friendly:
public class MyController: ApiController
{
private readonly IMyDependency dependency;
public MyController(IMyDependency dependency)
{
this.dependency = dependency;
}
public HttpResponseMessage Get()
{
var path = this.dependency.MapPath("~/App_Data");
...
}
}

For ApiControllers, build yourself a DelegatingHandler and push all of your goodies onto request.Properties. You can then retrieve them from your request whether you are testing or running live. The benefit is that you then have zero dependency on Session in your Controller.
MessageHandler
public class ContextHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
// get the goodies to add onto the request
var goodies = /* call to goodieGoodieYumYum */
// add our goodies onto the request
request.Properties.Add(Constants.RequestKey_Goodies, goodies);
// pass along to the next handler
return base.SendAsync(request, cancellationToken);
}
}
Controller Action
var goodies = (List<Goodie>)Request.Properties[Constants.RequestKey_Goodies];

Related

Confused about using the very same HTTPContextAccessor instance through the entire ASP.NET Core 3 application?

I've read about configuring IHttpContextAccessor as services.AddSingleton scope, but I also read about it is working "async local", and I am also aware of the sophisticated working of async in ASP.Net, I mean for example if a controller action method is async, and it await for an async call, then it may continue with an other thread, but magically some thread bound things with maintained (like HttpContext)
My concrete use case: I have to inject a MyConverter class to my EF Core DbContext which uses it in OnModelCreating. However this model is cached by the DbContext, so any subsequent request, even it will have a brand new instance of DbContext will use this very same model so the very same MyConverter instance. (even it has configured services.AddTransient). This MyConverter has a constructor and an injected IHttpContextAccessor, so based on the very similar reasons, it effectively will be also a singleton for all DbContext/MyConverter usages.
Question
This particular HttpContextAccessor instance which is created in the very first request will serve all the subsequent requests in the Web app lifecycle. Will it work correctly? Is there any (concurrency) trap here?
(Do I suppose correctly that it does not really matter if we use a single or multiple HttpContextAccessor instances, because its implementation of getting HttpContext will use the correct way including async local thread switch traps etc to return with the correct HttpContext?)
Short answer: register as services.AddHttpContextAccessor() and then you can inject IHttpContextAccessor wherever you want and it'll work as long as you're using it in the request's execution context. For instance you can't read HTTP request headers for code that was not initiated by a HTTP request.
You're right that the IHttpContextAccessor should be registered as a singleton. Instead of doing it yourself, the recommendation is to use AddHttpContextAccessor() extension method. See source code here. It internally registers an HttpContextAccessor as a singleton.
The code for HttpContextAccessor can be found here, which I'm also pasting below:
public class HttpContextAccessor : IHttpContextAccessor
{
private static AsyncLocal<HttpContextHolder> _httpContextCurrent = new AsyncLocal<HttpContextHolder>();
public HttpContext HttpContext
{
get
{
return _httpContextCurrent.Value?.Context;
}
set
{
var holder = _httpContextCurrent.Value;
if (holder != null)
{
// Clear current HttpContext trapped in the AsyncLocals, as its done.
holder.Context = null;
}
if (value != null)
{
// Use an object indirection to hold the HttpContext in the AsyncLocal,
// so it can be cleared in all ExecutionContexts when its cleared.
_httpContextCurrent.Value = new HttpContextHolder { Context = value };
}
}
}
private class HttpContextHolder
{
public HttpContext Context;
}
}
Since the HttpContext getter property returns from an async local field, you always get the HttpContext local to the execution context.
The HttpContext field is set in HttpContextFactory.Create() only if IHttpContextAccessor was registered with the DI. Source.
And HttpContextFactory.Create() is invoked from [HostingApplication](https://github.com/aspnet/AspNetCore/blob/v2.2.5/src/Hosting/Hosting/src/Internal/HostingApplication.cs) where the context is setup.

Access to container of Simple Injector MVC views

In a Sitecore project I've integrated Simple Injector using this article
It uses sitecore pipelines and then uses a method in App_start
namespace BBC.App_Start
{
public class SimpleInjector : IPackage
{
public void RegisterServices(Container container)
{
GetContainer.RegisterServices(container);
container.Register(() => new SitecoreContext(), Lifestyle.Scoped);
container.Register(() => new Container(), Lifestyle.Singleton);
}
}
}
Simply I can inject container into controller constructor but can't have container in View files.
I tried to declare a static property in App-start and save container to it. but still I'm getting no registration type in Views
What is the best way to have container object in views?
As Stephen suggests in his comment, the literal answer to your question is "you shouldn't do that - because it's not really the way MVC and DI are supposed to work". The more detailed answer goes something like this:
The job of your view is to present data that it has been passed via the Model. Views should not really contain logic. Very simple stuff like "if flag is false, hide this block of mark-up" is ok, but the more complex code to work out what the value of the flag is shouldn't be in the view.
MVC tries to make our website code better by encouraging you to separate presentation (the View) from data (the Model) and logic (the Controller). This should make our code easier to work with - So if you have processing that needs doing, then it should really be happening when your controller method runs.
If your view requires some special data, best practice suggests it should work it out in the controller method and pass it to the view in the model. The code might look more like this:
public class MyModel
{
public string SpecialData { get; set; }
}
public class MyController : Controller
{
public ActionResult DoSomething()
{
// do whatever processing is needed
var somethingCalculate = resultFromYourOtherObject();
// do other stuff
var model = new MyModel() { SpecialData = somethingCalculated };
return View(model);
}
}
And then the View just needs to accept the MyModel class as its model, and render the SpecialData property - no logic required.
I think also it's considered a bad idea to have calls to fetch objects from your DI container spread about your codebase. For MVC apps, generally your DI container gets wired in to the process of creating a controller for a request when the app starts up. Rather than passing about a DI Container into your controllers, the DI framework extends the Controller-creation process, and the container isn't exposed outside of this. When the MVC runtime needs to create a controller, the controller-creation logic uses the DI framework to fetch objects for all the controller's dependencies.
Without more detail about what you actually want to achieve, it's difficult to say what the "right" approach to creating your object(s) here is, but the two most common patterns are probably:
1) Constructor injection: Your controller has a parameter which accepts the object required. The DI container creates this object for you at the point where it creates the controller, so your controller gets all its dependencies when it is created. Good for: scenarios where you know how to create the object at the beginning of the request.
public interface IMySpecialObject
{
string DoSomething();
}
public class MyController : Controller
{
private IMySpecialObject _specialObject;
public MyController(IMySpecialObject specialObject)
{
_specialObject = specialObject;
}
public ActionResult RenderAView()
{
// do some stuff
var data = _specialObject.DoSomething();
return View(data);
}
}
As long as IMySpecialObject and a concrete implementation for it are registered with your DI container when your app starts up, all is well.
2) Factory classes: Sometimes, however, the object in question might be optional, or it might require data that's not available at controller-creation time to create it. In that case, your DI framework could pass in a Factory object to your controller, and this is used to do the construction of the special object later.
public interface ISpecialFactory
{
ISpecialObject CreateSpecialObject(object data);
}
public class MyController : Controller
{
private IMySpecialFactory _specialFactory;
public MyController(IMySpecialFactory specialFactory)
{
_specialFactory = specialFactory;
}
public ActionResult RenderAView()
{
// do some stuff
if( requireSpecialObject )
{
var data = getSomeData();
var specialObject = _specialFactory.CreateSpecialObject(data);
var data = _specialObject.DoSomething();
return View(data);
}
return View("someOtherView");
}
}
But a good book on using DI may suggest other approaches that fit your specific problem better.

How to access Request.Properties outside of Web API Controller

I'm setting a Property on Request.Properties inside a DelegatingHandler after I pluck some data out of a header on an incoming request to a Web API.
This all works fine. I can also access Request.Properties from within the controller as well as in my Action and Exception filters. However, I also need to access this data from outside of the controller (I call a business layer class from the controller). It is data I want to include in some logs in other places,
I can see HttpContext.Current from this class, and I can see the original header from here, so I guess I could pluck it out again, but since I have already done this and put it in the Properties it seems to make more sense to get it from there. However, I don't seem to have access to the Request.Properties from anywhere else.
If this isn't the right way to do this, how else would I pass around this per-request data so that it was accessible from anywhere on the stack in Web API?
I also need to access [Request.Properties] data from outside of the controller (I call a business layer class from the controller). It is data I want to include in some logs in other places... However, I don't seem to have access to the Request.Properties from anywhere else. If this isn't the right way to do this, how else would I pass around this per-request data so that it was accessible from anywhere on the stack in Web API?
You can get it from HttpContext.Current, though it is less than ideal. Keep in mind that if any other non-web applications consume the same business layer, then HttpContext.Current would be null. HttpContext.Current is only non-null when you are running in IIS, and an IIS thread is handling the execution of the request stack. If you ever plan to self-host the web api using OWIN without IIS, there will be no HttpContext.Current.
Personally, if the data really is important enough to be passed into the business layer to be logged, then I would just pass it to the business layer method:
public Task<HttpResponseMessage> SomeAction(SomeModel model) {
... other code
someBusinessLayerObject.SomeMethod(arg1, arg2, Request.Properties["myHeaderKey"]);
}
...If you need other values from Request.Properties, then you can just pass the whole dictionary to the methods that will end up using its values.
A third option if you are using an inversion of control container would be to add some kind of scoped object dependency class and put the data in there. Then constructor inject it into your business layer class:
public interface IHaveRequestData {
IDictionary<string, object> Properties { get; set; }
}
public class RequestData : IHaveRequestData {
public IDictionary<string, object> Properties { get; set; }
}
// ioc registration pseudocode
iocContainer.Register<IHaveRequestData, RequestData>(Lifetime
.WhateverYouNeedSoThatOneOfTheseGetsCreatedForEachWebRequest);
public class SomeController : ApiController {
private readonly IHaveRequestData RequestData;
public SomeController(IHaveRequestData requestData) {
RequestData = requestData;
}
public Task<HttpResponseMessage> SomeAction() {
// you may even be able to do this part in an action filter
RequestData.Properties = Request.Properties;
}
}
public class SomeBusinessLayerComponent {
private readonly IHaveRequestData RequestData;
private readonly ILog Log;
public SomeBusinessLayerComponent(IHaveRequestData requestData, ILog log) {
RequestData = requestData;
Log = log;
}
public Task SomeMethod() {
Log.Info(RequestData["myHeader"]);
}
}

Injection of Request Scope objects into MVC ActionFilterAttribute

I have a shopping cart service IShoppingCartService that is defined with Ninject as being InRequestScope
this.Bind<IShoppingCartService>().To<ShoppingCartService>().InRequestScope();
It loads the user's shopping cart and caches it internally. Once the request is over then the service object goes away.
I needed to access the shopping cart within an ActionFilter so I used the [Inject] attribute.
public class MyActionFilterAttribute : ActionFilterAttribute
{
[Inject]
public IShoppingCartService ShoppingCartService
{
get; set;
}
}
I can then use it in the action filter like this
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
var cart = ShoppingCartService.ShoppingCart;
...
}
Now for the weird part. This has been working just fine for a year or more - and then suddenly (after recently upgrading Ninject and MVC) I notice that the shopping cart is being cached (i.e. not InRequestScope).
On further research I see that ActionFilters are singletons (I verified this given that the constructor was only ever called once). So once an instance of the shopping cart is loaded it is locked in forever.
So my question is - how on earth did this ever work? Did something recently change in Ninject or MVC that could have allowed this to work before.
My fix right now is to do the following :
public IShoppingCartService ShoppingCartService
{
get
{
var scs = (IShoppingCartService) DependencyResolver.Current.GetService(typeof(IShoppingCartService));
return scs;
}
}
I'm really confused though as to how this ever could have worked - and it definitely did. What should I have done instead?
Maybe while the filter attribute was only instantiated once, the property was [Injected]-ed every time the page as hit. But let's look forward :)
In 2010 a "new" way was implemented in Ninject.MVCx (x =3, 5,..) on how to inject stuff into action filters. It doesn't need to rely on attributes and it supports constructor injection. Here's how it looks like:
(Fair warning: i don't usually do asp.net development and i didn't get to try out if the following does change anything about the lifecycle of the IActionFilter, so you'll have to try it out yourself. If you do, please provide feedback)
public class MyActionFilter : IActionFilter
{
private readonly IShoppingCartService shoppingCartService;
public MyActionFilter(IShoppingCartService shoppingCartService)
{
this.shoppingCartService = shoppingCartService;
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
var cart = ShoppingCartService.ShoppingCart;
...
}
}
The filter then needs to be bound by a special method BindFilter:
this.BindFilter<MyActionFilter>(FilterScope.Action, 0)
.WhenControllerTypeIs<YourController>();
which would apply it to all the actions of YourController.
There's also other targets you can apply the filter to, by using:
// Is applied to all actions of controllers which have the FooAttribute
this.BindFilter<MyActionFilter>(FilterScope.Action, 0)
.WhenControllerHas<FooAttribute>();
// Is applied to all actions which have the FooAttribute
this.BindFilter<MyActionFilter>(FilterScope.Action, 0)
.WhenActionHas<FooAttribute>();
// Is applied to all actions named Index
this.BindFilter<MyActionFilter>(FilterScope.Action, 0)
.When((controllerContext, actionDescriptor) =>
actionDescriptor.ActionName == "Index");
There's some more info on that which can be found in a great article by Remo Gloor: Official Ninject MVC extension gets support for MVC3 (chapter Dependency Injection for filters)

How to correctly dispose objects registered with Autofac

I've implemented Unit of Work/Repository pattern, as described here, but I'm also using autofac and constructor injection, so I registered UnitOfWork and DbContext (PsyProfContext) class like this:
builder.Register(context => new PsyProfContext()).InstancePerHttpRequest();
builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerHttpRequest();
And everything works great!
Except for one thing: I'm also using enterprise library logging block, and I have implemented CustomTraceListener which is using Entity Framework to write log entry into the database.
My controller looks like this (it is empty because at the moment I just tried to verify if all the things (IoC, logging, entity framework) are working):
public class HomeController : Controller
{
private readonly UnitOfWork unitOfWork;
public HomeController(IUnitOfWork unitOfWork)
{
this.unitOfWork = (UnitOfWork) unitOfWork;
}
//
// GET: /Home/
public ActionResult Index()
{
throw new HttpException();
return View();
}
protected override void Dispose(bool disposing)
{
unitOfWork.Dispose();
base.Dispose(disposing);
}
}
And in the Write method of the CustomTraceListener class, I've tried to Resolve UnitOfWork:
DependencyResolver.Current.GetService<IUnitOfWork>() as UnitOfWork;
But I get an instance which is already disposed! so I've put some breakpoints and found out that Dispose method of the controller is called before the Write method of the CustomTraceListener class, so in the end I didn't found other solution than using DbContext (PsyProfContext) directly:
public override void Write(object o)
{
using (var conext = new PsyProfContext())
{
var customLogEntry = o as CustomLogEntry;
if (customLogEntry != null)
{
var logEntry = new LogEntry
{
//a bunch of properties
};
conext.Exceptions.Add(logEntry);
conext.SaveChanges();
}
}
}
But I don't like this solution! What's the point to use UnitOfWork and Repository pattern if you access DbContext object directly. Or what's the point in using DI in project if you create a registered object manually in some cases.
So I wanted to hear your opinion, about how to deal with this kind of situations? Is my current implementation fine, or it is definitely wrong and I should think about another one.
Any help will be greatly appreciated and any ideas are welcome!
It looks like you may have a couple of problems.
First, if you're manually disposing the unit of work object in your controller, your controller should take an Owned<IUnitOfWork> in the constructor. When the request lifetime is disposed it will automatically dispose of any IDisposable components - including the controller and any resolved dependencies - unless you specify somehow that you're going to take over ownership of the lifetime. You can do that by using Owned<T>.
public class HomeController : Controller
{
Owned<IUnitOfWork> _uow;
public HomeController(Owned<IUnitOfWork> uow)
{
this._uow = uow;
}
protected override void Dispose(bool disposing)
{
if(disposing)
{
this._uow.Dispose();
}
base.Dispose(disposing);
}
}
(Note a minor logic fix in the Dispose override there - you need to check the value of disposing so you don't double-dispose your unit of work.)
Alternatively, you could register your units of work as ExternallyOwned, like
builder
.RegisterType<UnitOfWork>()
.As<IUnitOfWork>()
.ExternallyOwned()
.InstancePerHttpRequest();
ExternallyOwned also tells Autofac that you'll take control of disposal. In that case, your controller will look like it does already. (Generally I like to just let Autofac do the work, though, and not take ownership if I can avoid it.)
In fact, looking at the way things are set up, you might be able to avoid the disposal problem altogether if you let Autofac do the disposal for you - the call to DependencyResolver would return the unit of work that isn't disposed yet and it'd be OK.
If that doesn't fix it... you may want to add some detail to your question. I see where your controller is using the unit of work class, but I don't see where it logs anything, nor do I see anything in the listener implementation that's using the unit of work.
(Also, as noted in the first comment on your question, in the constructor of your controller you shouldn't be casting your service from IUnitOfWork to UnitOfWork - that's breaking the abstraction that the interface was offering in the first place.)