Reputation: 452
I'm having trouble using the HttpContext class. I can access HttpContext but can't call it's functions.
I want to use HttpContext.Authentication inside a helper class I'm writing.
I can't write anything like this (see below) inside my helper class:
private void SignInUser()
{
... Code
await HttpContext.Authentication.SignInAsync(..);
}
However, I can access HttpContext inside my controller class.
I'd appreciate any help. Thanks in advance.
Upvotes: 1
Views: 4550
Reputation: 64121
If you wannt to use a helper class which signs in a user, you should make an extension method instead, which either wraps around IHttpContextAccessor
or HttpContext
itself.
public static class HttpContextExtensions
{
public static void SignInUser(this HttpContext context)
{
await context.Authentication.SignInAsync(..);
}
public static void SignInUser(this.IHttpContextAccessor contextAccessor)
{
// Calls the method from above
contextAccessor.HttpContext.SignInUser();
}
}
Or if you have a bigger dependency chain and require other injected services, convert it into a injectable class:
public class UserLogonService : IUserLogonService
{
private readonly IHttpContextAccessor contextAccessor;
public UserLogonService(IHttpContextAccessor contextAccessor)
{
if(contextAccessor==null)
throw new ArgumentNullException(nameof(contextAccessor));
this.contextAccessor = contextAccessor;
}
public void SingInUser()
{
contextAccessor.HttpContext.SignInUser();
}
}
and in Startup.Configure
method:
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddSingleton<IUserLogonService, UserLogonService>();
Now you can inject IUserLogonService
everywhere in your project via constructor, i.e.
public class MyController
{
private readonly IUserLogonService userLogon;
public MyController(IUserLoggonService userLogon)
{
this.userLogon = userLogon;
}
public async Task<IActionResult> Login()
{
await userLogon.SignInUser();
}
}
It's clean, decoupled and can easily be unit tested, which you can't do with a static helper class.
Upvotes: 3
Reputation: 124
First create file HttpContext.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
namespace System.Web
{
public static class HttpContext
{
private static IHttpContextAccessor _contextAccessor;
public static Microsoft.AspNetCore.Http.HttpContext Current => _contextAccessor.HttpContext;
internal static void Configure(IHttpContextAccessor contextAccessor)
{
_contextAccessor = contextAccessor;
}
}
public static class StaticHttpContextExtensions
{
public static void AddHttpContextAccessor(this IServiceCollection services)
{
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
}
public static IApplicationBuilder UseStaticHttpContext(this IApplicationBuilder app)
{
var httpContextAccessor = app.ApplicationServices.GetRequiredService<IHttpContextAccessor>();
System.Web.HttpContext.Configure(httpContextAccessor);
return app;
}
}
}
Next in you startup file
public void ConfigureServices(IServiceCollection services)
...
services.AddTransient<IHttpContextAccessor, HttpContextAccessor>();
services.AddHttpContextAccessor();
...
Finally for example out of controllers, if you need current user name
var currentUsername = !string.IsNullOrEmpty(System.Web.HttpContext.Current?.User?.Identity?.Name)
? System.Web.HttpContext.Current.User.Identity.Name
: "Anonymous";
I tested whit ASPNET Core 1.0 and 1.1
EDIT Sorry i forgot in your startup file in section configure add this:
public void Configure(IApplicationBuilder app)
...
app.UseStaticHttpContext();
...
Upvotes: 3