9.9 KiB
title | author | description | monikerRange | ms.author | ms.custom | ms.date | no-loc | uid | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Access HttpContext in ASP.NET Core | coderandhiker | HttpContext in ASP.NET Core. HttpContext isn't thread-safe and can throw NullReferenceException. | >= aspnetcore-3.1 | riande | mvc | 5/5/2020 |
|
fundamentals/httpcontext |
Access HttpContext in ASP.NET Core
:::moniker range=">= aspnetcore-6.0"
ASP.NET Core apps access HttpContext
through the xref:Microsoft.AspNetCore.Http.IHttpContextAccessor interface and its default implementation xref:Microsoft.AspNetCore.Http.HttpContextAccessor. It's only necessary to use IHttpContextAccessor
when you need access to the HttpContext
inside a service.
Use HttpContext from Razor Pages
The Razor Pages xref:Microsoft.AspNetCore.Mvc.RazorPages.PageModel exposes the xref:Microsoft.AspNetCore.Mvc.RazorPages.PageModel.HttpContext?displayProperty=nameWithType property:
public class IndexModel : PageModel
{
public void OnGet()
{
var message = HttpContext.Request.PathBase;
// ...
}
}
The same property can be used in the corresponding Razor Page View:
@page
@model IndexModel
@{
var message = HttpContext.Request.PathBase;
// ...
}
Use HttpContext from a Razor view in MVC
Razor views in the MVC pattern expose the HttpContext
via the xref:Microsoft.AspNetCore.Mvc.Razor.RazorPage.Context%2A?displayProperty=nameWithType property on the view. The following example retrieves the current username in an intranet app using Windows Authentication:
@{
var username = Context.User.Identity.Name;
// ...
}
Use HttpContext from a controller
Controllers expose the xref:Microsoft.AspNetCore.Mvc.ControllerBase.HttpContext%2A?displayProperty=nameWithType property:
public class HomeController : Controller
{
public IActionResult About()
{
var pathBase = HttpContext.Request.PathBase;
// ...
return View();
}
}
Use HttpContext from middleware
When working with custom middleware components, HttpContext
is passed into the Invoke
or InvokeAsync
method:
public class MyCustomMiddleware
{
// ...
public async Task InvokeAsync(HttpContext context)
{
// ...
}
}
Use HttpContext from custom components
For other framework and custom components that require access to HttpContext
, the recommended approach is to register a dependency using the built-in Dependency Injection (DI) container. The DI container supplies the IHttpContextAccessor
to any classes that declare it as a dependency in their constructors:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews();
builder.Services.AddHttpContextAccessor();
builder.Services.AddTransient<IUserRepository, UserRepository>();
In the following example:
UserRepository
declares its dependency onIHttpContextAccessor
.- The dependency is supplied when DI resolves the dependency chain and creates an instance of
UserRepository
.
public class UserRepository : IUserRepository
{
private readonly IHttpContextAccessor _httpContextAccessor;
public UserRepository(IHttpContextAccessor httpContextAccessor) =>
_httpContextAccessor = httpContextAccessor;
public void LogCurrentUser()
{
var username = _httpContextAccessor.HttpContext.User.Identity.Name;
// ...
}
}
HttpContext access from a background thread
HttpContext
isn't thread-safe. Reading or writing properties of the HttpContext
outside of processing a request can result in a xref:System.NullReferenceException.
[!NOTE] If your app generates sporadic
NullReferenceException
errors, review parts of the code that start background processing or that continue processing after a request completes. Look for mistakes, such as defining a controller method asasync void
.
To safely do background work with HttpContext
data:
- Copy the required data during request processing.
- Pass the copied data to a background task.
- Do not reference
HttpContext
data in parallel tasks. Extract the data needed from the context before starting the parallel tasks.
To avoid unsafe code, never pass HttpContext
into a method that does background work. Pass the required data instead. In the following example, SendEmail
calls SendEmailCoreAsync
to start sending an email. The value of the X-Correlation-Id
header is passed to SendEmailCoreAsync
instead of the HttpContext
. Code execution doesn't wait for SendEmailCoreAsync
to complete:
public class EmailController : Controller
{
public IActionResult SendEmail(string email)
{
var correlationId = HttpContext.Request.Headers["X-Correlation-Id"].ToString();
_ = SendEmailCoreAsync(correlationId);
return View();
}
private async Task SendEmailCoreAsync(string correlationId)
{
// ...
}
}
Blazor and shared state
:::moniker-end
:::moniker range="< aspnetcore-6.0"
ASP.NET Core apps access HttpContext
through the xref:Microsoft.AspNetCore.Http.IHttpContextAccessor interface and its default implementation xref:Microsoft.AspNetCore.Http.HttpContextAccessor. It's only necessary to use IHttpContextAccessor
when you need access to the HttpContext
inside a service.
Use HttpContext from Razor Pages
The Razor Pages xref:Microsoft.AspNetCore.Mvc.RazorPages.PageModel exposes the xref:Microsoft.AspNetCore.Mvc.RazorPages.PageModel.HttpContext?displayProperty=nameWithType property:
public class IndexModel : PageModel
{
public void OnGet()
{
var message = HttpContext.Request.PathBase;
// ...
}
}
The same property can be used in the corresponding Razor Page View:
@page
@model IndexModel
@{
var message = HttpContext.Request.PathBase;
// ...
}
Use HttpContext from a Razor view in MVC
Razor views in the MVC pattern expose the HttpContext
via the xref:Microsoft.AspNetCore.Mvc.Razor.RazorPage.Context%2A?displayProperty=nameWithType property on the view. The following example retrieves the current username in an intranet app using Windows Authentication:
@{
var username = Context.User.Identity.Name;
// ...
}
Use HttpContext from a controller
Controllers expose the xref:Microsoft.AspNetCore.Mvc.ControllerBase.HttpContext%2A?displayProperty=nameWithType property:
public class HomeController : Controller
{
public IActionResult About()
{
var pathBase = HttpContext.Request.PathBase;
// ...
return View();
}
}
Use HttpContext from middleware
When working with custom middleware components, HttpContext
is passed into the Invoke
or InvokeAsync
method:
public class MyCustomMiddleware
{
public Task InvokeAsync(HttpContext context)
{
// ...
}
}
Use HttpContext from custom components
For other framework and custom components that require access to HttpContext
, the recommended approach is to register a dependency using the built-in Dependency Injection (DI) container. The DI container supplies the IHttpContextAccessor
to any classes that declare it as a dependency in their constructors:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddHttpContextAccessor();
services.AddTransient<IUserRepository, UserRepository>();
}
In the following example:
UserRepository
declares its dependency onIHttpContextAccessor
.- The dependency is supplied when DI resolves the dependency chain and creates an instance of
UserRepository
.
public class UserRepository : IUserRepository
{
private readonly IHttpContextAccessor _httpContextAccessor;
public UserRepository(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public void LogCurrentUser()
{
var username = _httpContextAccessor.HttpContext.User.Identity.Name;
service.LogAccessRequest(username);
}
}
HttpContext access from a background thread
HttpContext
isn't thread-safe. Reading or writing properties of the HttpContext
outside of processing a request can result in a xref:System.NullReferenceException.
[!NOTE] If your app generates sporadic
NullReferenceException
errors, review parts of the code that start background processing or that continue processing after a request completes. Look for mistakes, such as defining a controller method asasync void
.
To safely do background work with HttpContext
data:
- Copy the required data during request processing.
- Pass the copied data to a background task.
- Do not reference
HttpContext
data in parallel tasks. Extract the data needed from the context before starting the parallel tasks.
To avoid unsafe code, never pass the HttpContext
into a method that does background work. Pass the required data instead. In the following example, SendEmailCore
is called to start sending an email. The correlationId
is passed to SendEmailCore
, not the HttpContext
. Code execution doesn't wait for SendEmailCore
to complete:
public class EmailController : Controller
{
public IActionResult SendEmail(string email)
{
var correlationId = HttpContext.Request.Headers["x-correlation-id"].ToString();
_ = SendEmailCore(correlationId);
return View();
}
private async Task SendEmailCore(string correlationId)
{
// ...
}
}
Blazor and shared state
:::moniker-end