How MeController constractor calls? - asp.net-mvc

When I create default SPA template progect VS2013 creates MeController. Calling Get I have a user information. But when I create almost the same Controller, for example UserController, and copy-paste all from Me to User I do not have necessary info about user on breakpoint in the method:
// GET api/Me
public GetViewModel Get()
{
var user = UserManager.FindById(User.Identity.GetUserId());
return new GetViewModel() { Hometown = user.Hometown };
}
I don't uderstand this magic! I also do not see a caller of constractor and sender of userManager. Where is it?
public MeController(ApplicationUserManager userManager)
{
UserManager = userManager;
}

There is a default constructor in the MeController which gets called by default. In this case the UserManager, is got from the Owin contect as below
public ApplicationUserManager UserManager
{
get
{
return _userManager ?? HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>();
}
private set
{
_userManager = value;
}
}
Even if you copy this over to a new class like UserController, this should happen. Are you using any DI library like StrucuteMap/Unity etc? Certain DI controllers choose the 'greediest' constructor(the one with the maximum arguments). You could override that by using appropriate methods for that DI library(like this if you are using StructureMap)
In case you would want to use your own UserManager you could use your own implementation of UserManager and have it used. But if you are planning to stick with the default, this is already added in Startup.Auth.cs into the Owin pipeline.

Related

Configure Unity container per-request in OWIN middleware

I'm wanting to configure registrations in a Unity container being used by ASP.NET Web API 2 based on properties of a HTTP request. For example, a request to /api/database1/values should result in a Unity container configuration with an IDbContext configured for database1, while a request to /api/database4/values will get an IDbContext configured for database4.
I've gotten so far as using UnityHierarchicalDependencyResolver as the dependency resolver, so types registered with HierarchicalLifetimeManager last only for the lifetime of the request. This works well for getting types resolved per request. But how to get them registered per request using OWIN middleware is beyond me.
In my middleware, a call to System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(IUnityContainer)) gets an instance of IUnityContainer, but it's the same container for all requests, including any registrations from previous requests.
By encapsulating UnityHierarchicalDependencyResolver with my own implementation of IDependencyResolver I can see that IDependencyResolver.BeginScope isn't called until much later in the process. So the problem would seem to be that the child container isn't created until Web API wakes up, long after my middleware calls Next(..).
Is there a way I can get the scope of my dependency resolver to start sooner? Is there some other strategy that I'm missing. In case it makes any difference, I'm hosting in IIS, but favouring the OWIN middleware approach.
Update
This isn't an answer, and it's too big for a comment, but after struggling to solve this with Unity I decided to switch to Autofac and it all just fell into place.
The Autofac OWIN packages (Autofac.Mvc5.Owin, Autofac.Owin, Autofac.WebApi2.Owin) make it dead easy to use Autofac within the OWIN pipeline and ensure appropriate lifetime management in ASP.NET MVC and Web API. This was the missing link.
I couldn't find a way to reconfigure the container per-request, but it did at least make it possible to configure a factory per-request (so yes, #Haukinger and #alltej, you were right to push in that direction.
So I register a factory like:
builder.RegisterType<DataDependencyFactory>().InstancePerRequest();
And register the create method of that factory like:
builder
.Register(c => c.Resolve<DataDependencyFactory>().CreateDataDependency())
.As<IDataDependency>()
.InstancePerRequest();
Registering the factory this way is particularly useful, because downstream dependents don't need to be aware of the factory. I like this because my dependents don't need a factory, they need an instance. The container bends to the needs of my dependents, not the other way around :)
Then, in a piece of OWIN middleware, I resolve the factory, and set a property on it according to the properties of the request. Subsequent resolution of IDataDependency in an MVC or Web API controller, or anything else later in the OWIN pipeline, will get an instance configured according to the property on the factory.
Based on your api URL ("/api/database4/values"), I suggest that you create a filter attribute(e.g. DbIdFilter) so that you can reuse the filter attribute to other controller methods that follow similar url path/segment like this below:
[HttpGet]
[DbIdFilter]
[Route("{databaseId}/values")]
public IHttpActionResult GetValues()
{
return Ok();
}
[HttpGet]
[DbIdFilter]
[Route("{databaseId}/products")]
public IHttpActionResult GetProducts()
{
return Ok();
}
First, create the filter attribute:
public class DbIdFilterAttribute : ActionFilterAttribute
{
private readonly string _routeDataId;
private const string defaultRouteName = "databaseId";
public DbIdFilterAttribute():this(defaultRouteName)
{}
public DbIdFilterAttribute(string routeDataId)
{
_routeDataId = routeDataId;
}
public override void OnActionExecuting(HttpActionContext actionContext)
{
var routeData = actionContext.Request.GetRouteData();
var dbId = routeData.Values[_routeDataId] as string;
//here we create the db instance at the filter level.
DbInstanceFactory.RegisterDbInstance(dbId);
}
}
Next, create an instance factory that will register/resolve the db instance during runtime:
public class DbInstanceFactory : IDbInstanceFactory
{
public static IDbInstance RegisterDbInstance(string databaseId)
{
var factory = UnityConfig.GetConfiguredContainer().Resolve<IDbInstanceFactory>();
return factory.CreateInstance(databaseId);
}
public IDbInstance CreateInstance(string databaseId)
{
var container = UnityConfig.GetConfiguredContainer();
//container.RegisterType<IDbInstance, DbInstance>();
container.RegisterType<IDbInstance, DbInstance>(new InjectionConstructor(databaseId));
var dbInstance = container.Resolve<IDbInstance>();
return dbInstance;
}
public IDbInstance GetInstance()
{
var container = UnityConfig.GetConfiguredContainer();
var dbInstance = container.Resolve<IDbInstance>();
return dbInstance;
}
}
public interface IDbInstanceFactory
{
IDbInstance CreateInstance(string databaseId);
IDbInstance GetInstance();
}
Register this factory class in UnityConfig.cs (or wherever you currently register the types):
container.RegisterType<IDbInstanceFactory, DbInstanceFactory>
(new ContainerControlledLifetimeManager());
It's registered ContainerControlledLifetimeManager since this factory does not have to be a per request.
So just a basic DbInstance class below(for clarity) that takes a parameter in the constructor (this parameter can be your connection string or a named connection):
public class DbInstance : IDbInstance
{
public string DbId { get; }
public DbInstance(string databaseId)
{
DbId = databaseId;
}
}
public interface IDbInstance
{
string DbId { get; }
}
In controller class, you can use it like this:
....
private IDbInstanceFactory _dbFactory;
public MyController(IDbInstanceFactory dbFactory)
{
_dbFactory = dbFactory;
}
// Alternate, if you want to use property injection instead of constructor injection
//[Dependency]
//public IDbInstanceFactory DbFactory { get; set; }
[HttpGet]
[DbIdFilter]
[Route("{databaseId}/test")]
public IHttpActionResult Test()
{
var db = _dbFactory.GetInstance();
return Ok(db.DbId);
}
...

AddTransient service using info from request

I've got an app in asp.net core using the built-in DI framework. I'd like to add a per-request (i.e. transient) service to the provider, but I'd like to actually make use of the request in its construction.
services.AddTransient<IMyService>(provider => { ... });
That's the closest overload I can find, but the provider object doesn't have anything about the current request. Is there a way to achieve what I'm trying to do, without upgrading to a more robust DI framework?
As posted in the comments, you can inject the IHttpContextAccessor into your services and access it, if the HttpContext is the only thing you need.
public class MyService : IMyService
{
private readonly HttpContext context;
public MyService(IHttpContextAccessor httpContextAccessor)
{
if(IHttpContextAccessor==null)
throw new ArgumentNullException(nameof(httpContextAccessor));
context = httpContextAccessor.HttpContext;
}
}
However, if you need something that's only available in the controller or outside of HttpContext, you can create a factory and pass the parameters to the factory
public class MyServiceFactory : IMyServiceFactory
{
// injecting the HttpContext for request wide service resolution
public MyServiceFactory(IHttpContextAccessor httpContextAccessor) { ... }
public IMyService Create(IDependency1 dep1, IDependency2 dep 2, string someRuntimeConfig)
{
IServiceProvider provider = this.context.RequestServices;
var myService = new MyService(provider.GetService<ISomeRepository>(), dep1, dep2, someRuntimeConfig);
return myService;
}
}
and then inject the IMyServiceFactory to your classes where you'd need IMyService.

How to get the OWIN context on ASP.Net Identity?

I'm trying to get the DbContext from the current Owin context, so I can use a single context on my application, however, I'm getting a NullReferenceException.
I can access UserManager and RoleManager:
private ApplicationUserManager _userManager;
public ApplicationUserManager UserManager
{
get
{
return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
}
private set
{
_userManager = value;
}
}
They're configured how they came by default in the Identity sample project:
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
But trying to get the context to use it directly:
ApplicationDbContext context = HttpContext.GetOwinContext().Get<ApplicationDbContext>();
It always returns null on my controller. How can I get the current DbContext from the Owin context?
EDIT:
I was creating a new context to use with my generic repository
public AdminController()
{
AppContext = new ApplicationDbContext();
this.repoProyects = new GenericRepository<Proyect>(AppContext);
}
But it was creating a problem with entities being referenced from multiple contexts, so I'm trying to get the current Owin context like this:
public AdminController()
{
this.AppContext = HttpContext.GetOwinContext().Get<ApplicationDbContext>();
this.repoProyects = new GenericRepository<Proyect>(AppContext);
}
HttpContext is always null from here, so I don't know how to get the context to pass it to my class.
I had the same issue using Identity Framework when I added some extra navigation properties to the ApplicationUser. If you set
appContext = HttpContext.Current.GetOwinContext().Get<ApplicationDbContext>();
in OnActionExecuting instead of in the constructor, then OWIN should be ready to return the DbContext that's in use at that point. OnActionExecuting kicks in before any action methods fire, so this should be early enough to be useful. Hope that helps.
I was missing the initialization of my entities in the Startup method ConfigureOauth...
app.CreatePerOwinContext<OwinAuthDbContext>(() => new OwinAuthDbContext());
Found the answer here: http://www.c-sharpcorner.com/UploadFile/ff2f08/token-based-authentication-using-Asp-Net-web-api-owin-and-i/

Unity MVC injecting current user

I am using the basic Unity MVC Nuget Bootstrapper.
I would like to Inject the currently logged in user into the services I am defining
_container.RegisterType<IDoSomethingService, DoSomethingService>();
such that DoSomethingService gets an ICurrentUser object or some form of resolver.
I am trying to avoid having to make calls like
DoSomethingService.DoSomething(currentUserUsingService,...);
Or in the constructor of all the MVC Controllers also avoiding setting:
DoSomethingService.CurrentUSer = User.Identity.Name;
In my projects I use next:
public interface ICurrentUserService
{
int? GetId();
}
I register next implementation:
public class CurrentUserService: ICurrentUserService
{
public int? GetId()
{
if (!HttpContext.Current.User.Identity.IsAuthenticated)
return null;
return int.Parse(HttpContext.Current.User.Identity.Name);//When auth - id stored in cookie
}
}
_container.RegisterType<ICurrentUserService, CurrentUserService>();
And make my services depends on ICurrentUserService (by using ctor parameter) or pass userId into methods of my services in controllers.

MVC3 - How to correctly inject dependencies with MVC3 and Ninject?

I am attempting to redesign an existing application using dependency injection with Ninject in MVC3. Here is a portion of the legacy behavior I'm having difficulty with (and yes I know its bad, that's why I'm trying to refactor it):
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext);
MyUserSession userSession = filterContext.HttpContext.Session[SESSIONKEY_USER] as MyUserSession;
// if session empty, rebuild user information
if (userSession == null)
{
string userName = HttpContext.User.Identity.Name;
userSession = new MyUserSession();
using (ADSearcher ad = new ADSearcher(ldapPath, excludeOUString.Split(',')))
{
// get basic user information from Active Directory
ADUserInfo aduser = MyActiveDirectorySearcher.GetUserRecord(userName);
// ... set several properties queries from AD...
userSession.propertyXYZ = aduser.propXYZ
}
// if user can proxy as another indivudual, set property
using (EDMContainer db = new EDMContainer())
{
if (db.Proxies.Any(p => p.ProxyLogin == userSession.userLogin))
userSession.CanProxy == true;
}
// save new user object to session
filterContext.HttpContext.Session[SESSIONKEY_USER] = userSession;
if(userSession.canProxy)
filterContext.Result = RedirectToAction("Proxy", "Home");
return;
}
}
So currently, the controller users several objects directly: Session, ActiveDirectorySearch, EF Database. I understand it would be better to create a class that exposes a single method "GetUser" masking all the complexity but I'm struggling with how to inject the dependencies.
If I create a class SomeUserProvider, it will also need access to the Session to check for existing user information, and then ActiveDirectorySearcher and Database to rebuild the user properties if session was empty.
My confusion is over the fact that the controller itself will need access to ActiveDirectorySearcher in other action methods and then other classes will also use the same database. Do I inject an IActiveDirSearchrer into the controller's constructor and then pass it down into the ISomeUserProvider? What about IMyDatabase? Is it also injected in controller constructor and passed down?
And last but not lease, ISessionWrapper? I know session is controversial, but I need to track who the current user is and who they are proxied as during each request (GETs and POSTs). So, does that get injected as well?
If the answer is yes to each of those, is it bad to have 3+ injected contstuctor parameters?
I realize my question may be vague, so please ask for clarification where needed. I am open to any and all suggestions and recommendations. My goal is to learn how to do it correctly.
Thanks.
I'm not certain if this is exactly what you're looking for, but this should get you started down the path of refactoring your app for DI
public class YourController : Controller
{
private readonly ISessionWrapper _sessionWrapper;
private readonly IActiveDirSearcher _adSearcher;
private readonly IMyDatabase _database;
public YourController(ISessionWrapper sessionWrapper,
IActiveDirSearcher adSearcher, IMyDatabase database)
{
this._sessionWrapper = sessionWrapper;
this._adSearcher = adSearcher;
this._database = database;
}
// now all actions in this controller have a _sessionWrapper,
// _adSearcher and _database
}
Then you have to bind your injections the Ninject way. Subclass your application from NinjectHttpApplication and override OnApplicationStarted and CreateKernel
public class MvcApplication : NinjectHttpApplication
{
// ...
protected override void OnApplicationStarted()
{
base.OnApplicationStarted();
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
protected override IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<ISessionWrapper>().To<YourSessionWrapperImplementation>();
kernel.Bind<IActiveDirSearcher>().To<YourADImplementation>();
kernel.Bind<IMyDataBase>().To<YourEDMContainerIThink>();
return kernel;
}
}
The implementations of these appear to be described in your question. However, you mentioned other actions (and other classes) depend on these implementations. Good news--the bindings in CreateKernel will take care of any missing dependencies elsewhere in your app. e.g.
public class MyActiveDirImplementation : IActiveDirSearcher
{
private readonly IMyDatabase _database;
// injected automagically WOOHOO!
public MyActiveDirImplementation(IMyDatabase database)
{
this._database = database;
}
public ADUserInfo GetUserRecord(string username)
{
return _database.GetSomeUserRecord(username);
}
}
You could, of course, similarly implement your ISessionWrapper or IMyDatabase

Resources