'Is it the right way to use IHttpContextAccessor in a class?
I am working on an Asp.Net Core web application running on .NET Core 3.1.
For a wizard form, I am relying on a User class that holds the data stored in session. As we can access HttpContext from a controller, I had this GetUser() method inside my controller to retrieve session data when necessary :
private User GetUser()
{
var session = HttpContext.Session.GetComplexData<User>("user");
if (session == null)
{
User user = new User();
HttpContext.Session.SetComplexData("user", user);
}
return (User)HttpContext.Session.GetComplexData<User>("user");
}
Then I wanted to move that GetUser() method inside the User class so I used DI to provide that class's ctor with IHttpContextAccessor :
public class User
{
private readonly IHttpContextAccessor _contextAccessor;
public User(IHttpContextAccessor contextAccessor)
{
_contextAccessor = contextAccessor;
}
// fields removed here to keep it short
public User GetUser()
{
var session = _contextAccessor.HttpContext.Session.GetComplexData<User>("user");
if (session == null)
{
User user = new User(_contextAccessor);
_contextAccessor.HttpContext.Session.SetComplexData("user", user);
}
return (User)_contextAccessor.HttpContext.Session.GetComplexData<User>("user");
}
}
But then, in order to use that GetUser() method in my controller(s), I also have to provide this controller's ctor with IHttpContextAccessor as my User needs it to be instantiated :
public class NewController : Controller
{
private readonly IHttpContextAccessor _contextAccessor;
public NewController(IHttpContextAccessor contextAccessor)
{
_contextAccessor = contextAccessor;
}
[HttpGet]
public IActionResult Step1()
{
// Get session data
User user = new User(_contextAccessor); // <--
user = user.GetUser();
// Other code...
// ---
return View("Step1");
}
}
So my question is... Is it the right way to do it?
Or shall I just stick with my very first GetMethod() inside the controller without bothering with DI and duplicate it in other controllers if I need to access session there...?
Or perhaps you can show me something I don't know that would be more a good practice..
THanks
Solution 1:[1]
You don't want your User class to be tightly coupled to the HttpContext so your first method would be better. However, to improve readability and reusability (is that a word?) you could create users through an interface IUserManager and use dependency injection to provide the session there. The class would look something like this:
public class UserManager : IUserManager
{
private readonly IHttpContextAccessor _httpContextAccessor;
public UserManager(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public User Create()
{
// create user here using session in _httpContextAccessor
}
}
In order for this to work, don't forget to register the necessary dependencies in your container:
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpContextAccessor();
services.AddTransient<IUserManager, UserManager>();
}
Source material: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/http-context?view=aspnetcore-3.1#use-httpcontext-from-custom-components.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |