Is there any way to resolve the instance of a class at the controller level? I would like to override the previous instance created by unity and assign this new value via the controller.
Problem is I am not sure how to access the unity container in the web app controller.
Here is my code:
Repository:
public class UserRepository: IUserRepository
{
private UserInformation _userInfo;
public UserRepository(string headerValue)
{
_userInfo = LoadUserData(headerValue);
}
public UserInformation GetUserInfo()
{
return _userInfo;
}
}
public class UserInformation
{
public string FirstName;
public string LastName;
}
Unity Configuration:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
//Some code omitted
config.DependencyResolver = new UnityDependencyResolver(UnityConfig.RegisterComponents());
}
}
public static class UnityConfig
{
public static UnityContainer RegisterComponents()
{
//Unity Configuration
var container = new UnityContainer();
container.RegisterType<IUserRepository, UserRepository>(new InjectionConstructor("DummyHeaderValue"));
return container;
}
}
Controller:
public class CustomerController : ApiController
{
public CustomerController()
{
//Something like this
container.Resolve<UserRepository>(new InjectionConstructor(Request.GetHeader("RealHeaderValueFromHttpRequest")));
}
}
Then I should be able to use the updated UserRepository instance throughout the application.
Any thoughts on how to achieve this?
Edit: As pointed out by #Nkosi I don't have access to Request in controller constructor. So let me rephrase my question again:
How would I initialise UserRepository with UserInformation object which contains details about the current user? The reason I want to do this is that throughout my application I want user details and I don't want to pass User Id from each method
Something like this: From any method throughout application
UserInformation obj = _userRepository().GetUserInfo();
Create an abstraction to get access to the request
public interface IHeaderService {
string RealHeaderValueFromHttpRequest();
}
Its Implementation will have access to the context and request to get the desired functionality
public class HeaderService : IHeaderService {
public string RealHeaderValueFromHttpRequest() {
return HttpContext.Current.Request.Headers["RealHeaderValueFromHttpRequest"];
}
}
The service will now be explicitly injected into the dependent repository
public class UserRepository: IUserRepository {
private readonly IHeaderService headerService;
public UserRepository(IHeaderService headerService) {
this.headerService = headerService;
}
public UserInformation GetUserInfo() {
var headerValue = headerService.RealHeaderValueFromHttpRequest();
var _userInfo = LoadUserData(headerValue);
return _userInfo;
}
//...
}
The repository will then also be explicitly injected into dependent controllers.
public class CustomerController : ApiController {
private readonly IUserRepository repositoty;
public CustomerController(IUserRepository repositoty) {
this.repository = repository;
}
public IHttpActionResult SomeAction() {
//NOTE: Only access user info in a controller action
var userInfo = repository.GetUserInfo();
//... use user info.
}
//...
}
Now all that is left is to make sure all abstractions and their implementations are registered with the dependency container
public static class UnityConfig {
public static UnityContainer RegisterComponents() {
//Unity Configuration
var container = new UnityContainer();
container.RegisterType<IUserRepository, UserRepository>();
container.RegisterType<IHeaderService, HeaderService>();
return container;
}
}
Related
This question already has answers here:
How should I setup my repositories to use the same context?
(2 answers)
Closed 4 years ago.
Background
In my web application, I create stored procedures and then create an edmx file to use the stored procedures to handle all the database interaction.
But I started to wonder if I'm doing this right because, as you'll see in the example below,
I'm instantiating two instances of Context every time the Controller gets called even when the called method doesn't require database work
I'm instantiating an instances of Context in each repository, so when a request needs to get data from Repository A and B, I have two instances of Context.
Repository A
public class RepositoryA
{
private readonly Context _context;
public RepositoryA()
{
_context = new Context();
}
public List<CLASS> GetA(int id)
{
return _context.GetByID(id);
}
}
Repository B
public class RepositoryB
{
private readonly Context _context;
public RepositoryB()
{
_context = new Context();
}
public List<CLASS> GetB(int id)
{
return _context.GetByID(id);
}
}
Controller
public class Controller
{
private readonly IRepositoryA _reposA;
private readonly IRepositoryB _reposB;
public Controller() : this(new RepositoryA(), new RepositoryB())
{}
public Controller(IRepositoryA a, IRepositoryB b)
{
_respoA = a;
_reposB = b;
}
public ActionResult METHOD()
{
//do something with both RepositoryA and RepositoryB
var dataFromA = _reposA.GetA(ID);
var dataFromB = _reposB.GetB(ID);
return View(someData);
}
}
Now the question is: I'm not sure if this is supposed to be the normal implementation, so I've been trying to figure out how I can set this up in more efficient and testable way, and I tried something like this.
I believe that this design solves some of my concerns:
Service gets called every time Controller gets called, but Context doesn't get instantiated every time (Context gets instantiated per request).
When a service requires both Repository A and B, it uses the same Context
However, with how Service is set up, I can't unit test Service with test data because I can't use my mock repositories.
public class Controller
{
private Service _service;
public Controller()
{
_service = new Service();
}
public ActionResult METHOD()
{
_service.DoSomethingWithRepoAandB();
return View();
}
}
public class Service
{
public void DoSomethingWithRepoAandB()
{
using (var _context = new Context())
{
RepositoryA a = new RepositoryA(_context);
RepositoryB b = new RepositoryB(_context);
something = a.DoSomethingWithA();
otherThing = b.DoOtherThingWithB();
}
}
}
So, I'm thinking I should set up Service like this.
With this design, Context will be instantiated every time Controller gets called (unless I instantiate Service in a Controller method), but I can unit test by passing mock repositories.
public class Service
{
private readonly Context _context;
private IRepositoryA _a;
private IRepositoryB _b;
public Service()
{
_context = new Context();
_a = new RepositoryA(_context);
_b = new RepositoryB(_context);
}
// Pass Mock Repositories in unit tests
public Service(RepositoryA a, RepositoryB b)
{
_a = a;
_b = b;
}
public void DoSomethingWithRepoAandB()
{
something = _a.DoSomethingWithA();
otherThing =_b.DoOtherThingWithB();
}
}
Am I doing this completely wrong or on the ok track? I'd appreciate any advice.
Your services should NOT have any information about your context, that information should only be accessible by the repository, following SOLID principles.
The access of your layers should be as follows:
Controller -> Service -> Repository -> Context
On your IRepository interfaces, you will have the methods you're going to call, and you either instantiate them manually, but to implement it correctly, you'll have to setup your dependency injection.
Also, your Repositories constructors dont receive any context as a parameter, so you cant do something like this:
RepositoryA a = new RepositoryA(_context);
On another point, your controller shouldn't access repositories as well, as it breaks your architecture
public ActionResult METHOD()
{
//do something with both RepositoryA and RepositoryB
var dataFromA = _reposA.GetA(ID);
var dataFromB = _reposB.GetB(ID);
return View(someData);
}
Here's the correct code, for further understanding:
public class RepositoryA : IRepositoryA
{
private readonly Context _context;
public RepositoryA(Context context)
{
_context = context;
}
public List<CLASS> GetA(int id)
{
return _context.GetByID(id);
}
}
public interface IRepositoryA
{
List<CLASS> GetA(int id);
}
public class RepositoryB : IRepositoryB
{
private readonly Context _context;
public RepositoryB(Context context)
{
_context = context;
}
public List<CLASS> GetB(int id)
{
return _context.GetByID(id);
}
}
public interface IRepositoryB
{
List<CLASS> GetB(int id);
}
public class Controller
{
private IService _service;
public Controller(IService service)
{
_service = service;
}
public ActionResult METHOD(int id)
{
//do something with both RepositoryA and RepositoryB THROUGH the service. The service needs to hold the business rules, and repositories should only care about querying data and handling contexts.
var data = _service.DoSomethingWithRepoAandB(id)
return View(data);
}
}
public class Service : IService
{
private IRepositoryA _a;
private IRepositoryB _b;
// Pass Mock Repositories in unit tests -> PS: You can't have 2 constructors if you're using dependency injection.
public Service(RepositoryA a, RepositoryB b)
{
_a = a;
_b = b;
}
public void DoSomethingWithRepoAandB(int id)
{
var something = _a.GetA(id);
var otherThing = _b.GetB(id);
}
}
public interface IService
{
void DoSomethingWithRepoAandB(int id);
}
public class Bootstrapper
{
//this class should be in a separated assembly, responsible for handling the dependency injection. Using Simple Injection syntax just as an example
public static void RegisterServices(Container container) //IoC Container
{
container.Register<IService, Service>(Lifestyle.Scoped);
container.Register<IRepositoryA, RepositoryA>(Lifestyle.Scoped);
container.Register<IRepositoryB, RepositoryB>(Lifestyle.Scoped);
container.Register<Context>(() => {
var options = // Configure your ContextOptions here
return new Context(options);
});
}
}
public class Startup
{
//This is your startup configuration if you're using WebApi. If you're on MVC, you can do this on your Global.asax
public void Configuration()
{
var container = new Container();
container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();
BootStrapper.RegisterServices(container);
}
}
I have some problems with correctly working HttpContext.Current.User.Identity. From Controller constructor this doesn't work, I have to implement this to some method. Look at this example.
public class SomeControler : ApiController
{
private UserData userData;
// NOT WORKING
public ChartsController(
RegisteredUserData registeredUserData,
NotLoggedInUserData NotLoggedInUserData
{
var isAuthenticated = HttpContext.Current.User.Identity.IsAuthenticated;
this.userData = isAuthenticated
? (IUserData)registeredUserData
: (IUserData)NotLoggedInUserData;
}
// WORKING
public SomeMethod(
RegisteredUserData registeredUserData,
NotLoggedInUserData NotLoggedInUserData
{
var isAuthenticated = HttpContext.Current.User.Identity.IsAuthenticated;
this.userData = isAuthenticated
? (IUserData)registeredUserData
: (IUserData)NotLoggedInUserData;
}
}
How I can fix this? I spent a lot of time for answer in web but i didnt get this.
Regards.
edit
I found an answer. Is it good solution ?
public class SomeControler : ApiController
{
private RegisteredUserData registeredUserData;
private NotLoggedInUserData notLoggedInUserData;
private UserData userData
{
get
{
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
return registeredUserData;
}
return notLoggedInUserData;
}
}
public ChartsController(
RegisteredUserData registeredUserData,
NotLoggedInUserData notLoggedInUserData
{
this.registeredUserData = registeredUserData;
this.notLoggedInUserData = notLoggedInUserData;
}
}
First, the request and HttpContext is not available yet in the construct of the controller because of where in the request flow the controller is initialized. You have to access it in an action where by then, the request and context would have been fully realized.
Next do not couple your controllers to HttpContext. It makes your code difficult to test and maintain.
Extract the desired information in a service abstraction.
public interface IUserDataAccessor {
IUserData UserData { get; }
}
public class UserDataAccessor : IUserDataAccessor {
private readonly RegisteredUserData registeredUserData;
private readonly NotLoggedInUserData notLoggedInUserData;
public UserDataAccessor(
RegisteredUserData registeredUserData,
NotLoggedInUserData notLoggedInUserData) {
this.registeredUserData = registeredUserData;
this.notLoggedInUserData = notLoggedInUserData;
}
public IUserData UserData {
get {
if (HttpContext.Current?.User?.Identity?.IsAuthenticated) {
return registeredUserData;
}
return notLoggedInUserData;
}
}
}
This allows the controller to remain lean with just the dependency on the abstraction.
public class ChartsController : ApiController {
private readonly IUserDataAccessor accessor;
public ChartsController(IUserDataAccessor accessor) {
this.accessor = accessor;
}
[HttpGet]
public IHttpActionResult SomeAction() {
var userData = accessor.UserData;
//...do something associated with user data
return OK();
}
}
Finally make sure that the abstraction and it's implementation a registered with your dependency container in your composition root.
NotificationHubConnectionSettings.cs file to fetch connection string from web.config
public class NotificationHubConnectionSettings
{
public NotificationHubClient Hub { get; set; }
public NotificationHubConnectionSettings()
{
Hub = NotificationHubClient.CreateClientFromConnectionString(ConfigurationManager.AppSettings["Microsoft.Azure.NotificationHubs.ConnectionString"], ConfigurationManager.AppSettings["NotificationHub"]);
}
}
Inside Bootstrapper.cs
using Unity dependency injection nuget
private static IUnityContainer BuildUnityContainer()
{
try
{
var container = new UnityContainer();
container.RegisterType<NotificationHubConnectionSettings>().RegisterType<NotificationHubConnectionSettings>(new HierarchicalLifetimeManager());
return container;
}
catch (Exception)
{
return null;
}
}
In HomeController.cs
want to implement dependency injection -
private readonly NotificationHubClient _hub;
public HomeController(NotificationHubConnectionSettings hub)
{
_hub = hub.Hub;
}
// POST api/register
// This creates a registration id
public async Task<string> Post(string handle = null)
{
string newRegistrationId = null;
if (handle != null)
{
var registrations = await _hub.GetRegistrationsByChannelAsync(handle, 100);
Is this correct way to implement dependency injection?
You should be using a interface type here.
Create a contract for INotificationHubConnectionSettings class in the form of a interface which dictates to your system all public methods and properties available.
public interface INotificationHubConnectionSettings
{
NotificationHubClient Hub { get; set; }
}
Then have your actual NotificationHubConnectionSettings class inherit from this interface;
public class NotificationHubConnectionSettings : INotificationHubConnectionSettings
{
public NotificationHubClient Hub { get; set; }
public NotificationHubConnectionSettings()
{
Hub = NotificationHubClient.CreateClientFromConnectionString(ConfigurationManager.AppSettings["Microsoft.Azure.NotificationHubs.ConnectionString"], ConfigurationManager.AppSettings["NotificationHub"]);
}
}
Now register the interface and class inside of UnityContainer and change your constructor to the following;
private readonly INotificationHubClient _hub;
public HomeController(NotificationHubConnectionSettings hub)
{
_hub = hub.Hub;
}
Always use interfaces for dependency injection.
I'm wiring up Autofac dependency injection within my ASP.NET MVC 5 web application using OWIN middleware (so using startup.cs instead of global.asax), and trying to use property injection to set a public variable within a Controller.
I'm playing around with property injection to have Autofac automatically set the Test property in the LoginController.
public interface ITest
{
string TestMethod();
}
public class Test : ITest
{
public string TestMethod()
{
return "Hello world!";
}
}
public class LoginController : Controller
{
public ITest Test { get; set; }
public LoginController()
{
var aaa = Test.TestMethod();
// Do other stuff...
}
}
Here's what my startup.cs looks like. I have been playing around, so some of this code might not be needed (or causing my issue?).
public class Startup
{
public void Configuration(IAppBuilder app)
{
var builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired();
builder.RegisterType<Test>().As<ITest>().SingleInstance();
builder.Register(c => new Test()).As<ITest>().InstancePerDependency();
builder.RegisterType<ITest>().PropertiesAutowired();
builder.RegisterType<LoginController>().PropertiesAutowired();
builder.RegisterModelBinderProvider();
builder.RegisterFilterProvider();
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
app.UseAutofacMiddleware(container);
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
// Some other stuff...
}
}
So, the 'Test' public property is always null, and therefore breaks on runtime.
Any ideas what could be my issue? Thanks advance for your help! :)
So, the 'Test' public property is always null, and therefore breaks on runtime.
It's not always null. It's null in the constructor because Autofac (actually ALL code) cannot set properties until the constructor is finished.
public class LoginController : Controller
{
public ITest Test { get; set; }
public LoginController()
{
// Test is null, will always be null here
var aaa = Test.TestMethod();
}
}
A super dummied down version of autofac does something like:
var controller = new LoginController();
controller.Test = new Test();
If you need to execute code after the property is set you could do something hacky like the following (but really you should just be using constructor injection):
public class LoginController : Controller
{
private ITest _test;
public ITest Test
{
get { return _test; }
set
{
var initialize = (_test == null);
_test = value;
if (initialize)
{
Initialize();
}
}
}
public LoginController()
{
}
private void Initialize()
{
var aaa = Test.TestMethod();
}
}
Again the more logical way would be to just do:
public class LoginController : Controller
{
private readonly ITest _test;
public LoginController(ITest test)
{
_test = test;
var aaa = _test.TestMethod();
// Do other stuff...
}
}
As an answer to my own question:
What would be the most elegant way to use Entity Framework with Generic Repository, in Service Stack, and to write Integration \ Unit Tests for service?
At the moment, this is how my structure looks like:
Generic repository layer:
public class GenericRepository<TEntity> where TEntity : class
{
internal DbContext Context;
//...
//CRUD Operations, etc.
}
Unit of work layer:
public class UnitOfWork : IDisposable
{
private readonly DbContext _context;
public UnitOfWork(DbContext ctx)
{
_context = ctx;
}
private bool _disposed;
private GenericRepository<User> _userRepository;
public GenericRepository<User> UserRepository
{
get { return _userRepository ?? (_userRepository = new GenericRepository<User>(_context)); }
}
//...
}
Business layer:
public class UserBusiness
{
public UnitOfWork UoW { get; set; }
public void AddUser(Models.User user)
{
//Map from domain model to entity model
var u = Mapper.Map<Models.User, DAL.Repository.User>(user);
UoW.UserRepository.Insert(u);
UoW.Save();
}
}
API project:
public class AppHost : AppHostBase
{
public AppHost() : base("Users Service", typeof(UsersService).Assembly) { }
//...
public override void Configure(Funq.Container container)
{
//...other configuration
//UoW registration
container.Register(c => new UnitOfWork(new DbContext("my-DB-connection"))).ReusedWithin(Funq.ReuseScope.Hierarchy);
//Business layer class registration
container.Register<UserBusiness>(c=>new UserBusiness {
UoW = c.Resolve<UnitOfWork>()
}).ReuseWithin(Funq.ReuseScope.Hierarchy);
}
}
public class UsersService : Service
{
public UserBusiness UB { get; set; }
public object Post(User u)
{
UB.AddUser(u);
//...
}
}
So when it comes to integration testing, I can just do something like this:
Declare _appHost
private ServiceStackHost _appHost;
And configure funq container like this:
public override void Configure(Funq.Container container)
{
//...create mocked context
var mockedContext = new Mock<IDbContext>();
mockedContext.Setup(x => x.Set<User>()).Returns(new List<User>
{
new User { ID = 1, FirstName = "John", LastName = "Doe" }
});
//(or use effort or any other way to create it)
container.Register(c => new UnitOfWork(mockedContext)).ReusedWithin(Funq.ReuseScope.Hierarchy);
}
And test as usual:
[Test]
public void Get_User_By_Id()
{
//...generate client instance (JsonServiceClient) etc.
var customer = client.Get(new GetCustomer { Id = 1 });
Assert.AreEqual("John", customer.FirstName);
///...
}
In addition to have all layers available for DI, and mocking, I also created IDbContext, IGenericRepository, IUnitOfWork, etc. interfaces.
I didn't include it here in order to keep this as simple as I could.
But I would like to hear if there's a better (more elegant way) to do it.