How to get Microsoft.AspNet.Http.HttpContext instance in Class Constructor using DI

前端 未结 4 1108
北海茫月
北海茫月 2021-01-03 23:18

I am building a throwaway application in MVC 6 and experimenting with different architectures for dependencies.

The problem I am facing is how to create a custom \'<

相关标签:
4条回答
  • 2021-01-03 23:46

    By injecting an HttpContext into your component you are violating the SOLID principles. To be more specifically, you are violating:

    • The Dependency Inversion Principle (DIP) because you depend on a framework type (the HttpContext).
    • The Interface Segregation Principle (ISP) because the HttpContext has many methods, while the consumer never uses them all.

    Both violations make it much harder to test your code. Although you can instead inject the IHttpContextAccessor as @victor suggests, this is still a violation of both the DIP and ISP, because this is an abstraction that is provided by the framework and you still depend on HttpContext. According to the DIP it is the client who should define the abstraction. This causes your code to be needlessly coupled to the framework.

    Instead you should strive to specify narrow role interfaces; interfaces that do one specific thing for you that is specific to the needs of your application. Injecting a big dictionary with string values (as what HttpContext is, is never very specific). From your question it's unclear what kind of data you need from our MyAppContext, but I expect something like information of the currently logged in user. For this you can define a specific IUserContext abstraction, for instance:

    public interface IUserContext {
        IPrincipal CurrentUser { get; }
    }
    

    An adapter that connects the application to the ASP.NET framework can be easily created for this abstraction:

    sealed class AspNetUserContextAdapter : IUserContext  {
        private readonly IHttpContextAccessor accessor;
        public AspNetUserContextAdapter(IHttpContextAccessor accessor) {
            this.accessor = accessor;
        }
        public IPrincipal CurrentUser => accessor.HttpContext.User;
    }
    

    This adapter does depend on IHttpContextAccessor, but this is okay, since the adapter is an infrastructural component located in the Composition Root. There are serveral ways to register this class, for instance:

    services.AddSingleton<IUserContext, AspNetUserContext>();
    
    0 讨论(0)
  • 2021-01-03 23:48

    Inject IHttpContextAccessor in the constructor

    0 讨论(0)
  • 2021-01-03 23:49

    In the startup class:

    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Mvc.Core;
    using Microsoft.Extensions.DependencyInjection;
    
    public void ConfigureServices(IServiceCollection services)
    {        
        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
        services.AddMvcCore();
    }
    

    In the controller:

    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Mvc.Core;
    
    private readonly IHttpContextAccessor _httpContextAccessor;
    
    public ServerSentEventController(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }
    
    0 讨论(0)
  • 2021-01-03 23:59

    Why would you pass the HttpContext in the constructor? Why not directly access it wherever you want?

    public MyAppContext(IDataService dataService)
        {
           HttpContext mycontext = HttpContext.Current;
           //do stuff here with mycontext
        }
    
    0 讨论(0)
提交回复
热议问题