1

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();
Shaggy
  • 5,422
  • 28
  • 98
  • 163
  • You are using a service locator pattern, when you should be using explicit dependency principle and inject the dependency into the constructor. `public CustomerController(IUserRepository repository) { ... }` – Nkosi Feb 07 '19 at 21:18
  • Also note that the request is not available as yet when accessed in the constructor of the controller. You will need to rethink the design of the repository and controller. – Nkosi Feb 07 '19 at 23:30
  • My main objective here is to initialize `UserRepository` constructor with the value from the Http request header using unity. Any thoughts? – Shaggy Feb 08 '19 at 01:42
  • I understand what you want to do. What I am telling you is you wont have access to the request in the constructor at the time that the repository is being initialized. – Nkosi Feb 08 '19 at 02:01
  • You should also review https://learn.microsoft.com/en-us/aspnet/web-api/overview/advanced/dependency-injection – Nkosi Feb 08 '19 at 02:13

1 Answers1

2

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;
    }
}
Nkosi
  • 235,767
  • 35
  • 427
  • 472
  • It looks good! I will try and let you know. Though I have one question, Is there any way I can use `HttpRequestMessage` instead of `HttpContext.Current.Request`. As if I use the prior one I won't be able to test my code end-to-end through integration testing (I am using OWIN to self-host for integration testing). – Shaggy Feb 10 '19 at 20:25
  • @Shaggy I just used it as a simple example. You should be able to extract the current HttpRequestMessage using Owin. – Nkosi Feb 10 '19 at 20:28
  • @Shaggy also when testing you can mock the service abstraction instead of using the coupled implementation. – Nkosi Feb 10 '19 at 20:36