aspnetcore/fundamentals/use-http-context.md
xref:Microsoft.AspNetCore.Http.HttpContext encapsulates all information about an individual HTTP request and response. An HttpContext instance is initialized when an HTTP request is received. The HttpContext instance is accessible by middleware and app frameworks such as Blazor Web Apps, Web API controllers, Razor Pages, SignalR, gRPC, and more.
HttpRequestxref:Microsoft.AspNetCore.Http.HttpContext.Request?displayProperty=nameWithType provides access to xref:Microsoft.AspNetCore.Http.HttpRequest. HttpRequest has information about the incoming HTTP request, and it's initialized when an HTTP request is received by the server. HttpRequest isn't read-only, and middleware can change request values in the middleware pipeline.
Commonly used members on HttpRequest include:
|Property|Description|Example|
|--|--|--|--|
|xref:Microsoft.AspNetCore.Http.HttpRequest.Path?displayProperty=nameWithType|The request path.|/en/article/getstarted|
|xref:Microsoft.AspNetCore.Http.HttpRequest.Method?displayProperty=nameWithType|The request method.|GET|
|xref:Microsoft.AspNetCore.Http.HttpRequest.Headers?displayProperty=nameWithType|A collection of request headers.|user-agent=Edge
x-custom-header=MyValue|
|xref:Microsoft.AspNetCore.Http.HttpRequest.RouteValues?displayProperty=nameWithType|A collection of route values. The collection is set when the request is matched to a route.|language=en
article=getstarted|
|xref:Microsoft.AspNetCore.Http.HttpRequest.Query?displayProperty=nameWithType|A collection of query values parsed from xref:Microsoft.AspNetCore.Http.HttpRequest.QueryString.|filter=hello
page=1|
|HttpRequest.ReadFormAsync()|A method that reads the request body as a form and returns a form values collection. For information about why ReadFormAsync should be used to access form data, see Prefer ReadFormAsync over Request.Form.|[email protected]|
|xref:Microsoft.AspNetCore.Http.HttpRequest.Body?displayProperty=nameWithType|A xref:System.IO.Stream for reading the request body.|UTF-8 JSON payload|
xref:Microsoft.AspNetCore.Http.HttpRequest.Headers?displayProperty=nameWithType provides access to the request headers sent with the HTTP request. There are two ways to access headers using this collection:
For information on efficiently handling headers that appear more than once, see A brief look at StringValues.
An HTTP request can include a request body. The request body is data associated with the request, such as the content of an HTML form, UTF-8 JSON payload, or a file.
xref:Microsoft.AspNetCore.Http.HttpRequest.Body?displayProperty=nameWithType allows the request body to be read with xref:System.IO.Stream:
HttpRequest.Body can be read directly or used with other APIs that accept stream.
[!NOTE] Minimal APIs supports binding xref:Microsoft.AspNetCore.Http.HttpRequest.Body?displayProperty=nameWithType directly to a xref:System.IO.Stream parameter.
The request body can only be read once, from beginning to end. Forward-only reading of the request body avoids the overhead of buffering the entire request body and reduces memory usage. However, in some scenarios, there's a need to read the request body multiple times. For example, middleware might need to read the request body and then rewind it so it's available for the endpoint.
The xref:Microsoft.AspNetCore.Http.HttpRequestRewindExtensions.EnableBuffering%2A extension method enables buffering of the HTTP request body and is the recommended way to enable multiple reads. Because a request can be any size, EnableBuffering supports options for buffering large request bodies to disk, or rejecting them entirely.
The middleware in the following example:
EnableBuffering. It must be called before reading the request body.An alternative way to read the request body is to use the xref:Microsoft.AspNetCore.Http.HttpRequest.BodyReader?displayProperty=nameWithType property. The BodyReader property exposes the request body as a xref:System.IO.Pipelines.PipeReader. This API is from I/O pipelines, an advanced, high-performance way to read the request body.
The reader directly accesses the request body and manages memory on the caller's behalf. Unlike HttpRequest.Body, the reader doesn't copy request data into a buffer. However, a reader is more complicated to use than a stream and should be used with caution.
For information on how to read content from BodyReader, see I/O pipelines PipeReader.
HttpResponsexref:Microsoft.AspNetCore.Http.HttpContext.Response?displayProperty=nameWithType provides access to xref:Microsoft.AspNetCore.Http.HttpResponse. HttpResponse is used to set information on the HTTP response sent back to the client.
Commonly used members on HttpResponse include:
|Property|Description|Example|
|--|--|--|--|
|xref:Microsoft.AspNetCore.Http.HttpResponse.StatusCode?displayProperty=nameWithType|The response code. Must be set before writing to the response body.|200|
|xref:Microsoft.AspNetCore.Http.HttpResponse.ContentType?displayProperty=nameWithType|The response content-type header. Must be set before writing to the response body.|application/json|
|xref:Microsoft.AspNetCore.Http.HttpResponse.Headers?displayProperty=nameWithType|A collection of response headers. Must be set before writing to the response body.|server=Kestrel
x-custom-header=MyValue|
|xref:Microsoft.AspNetCore.Http.HttpResponse.Body?displayProperty=nameWithType|A xref:System.IO.Stream for writing the response body.|Generated web page|
xref:Microsoft.AspNetCore.Http.HttpResponse.Headers?displayProperty=nameWithType provides access to the response headers sent with the HTTP response. There are two ways to access headers using this collection:
An app can't modify headers after the response has started. Once the response starts, the headers are sent to the client. A response is started by flushing the response body or calling xref:Microsoft.AspNetCore.Http.HttpResponse.StartAsync(System.Threading.CancellationToken)?displayProperty=nameWithType. The xref:Microsoft.AspNetCore.Http.HttpResponse.HasStarted?displayProperty=nameWithType property indicates whether the response has started. An error is thrown when attempting to modify headers after the response has started:
System.InvalidOperationException: Headers are read-only, response has already started.
[!NOTE] Unless response buffering is enabled, all write operations (for example, xref:Microsoft.AspNetCore.Http.HttpResponseWritingExtensions.WriteAsync%2A) flush the response body internally and mark the response as started. Response buffering is disabled by default.
An HTTP response can include a response body. The response body is data associated with the response, such as generated web page content, UTF-8 JSON payload, or a file.
xref:Microsoft.AspNetCore.Http.HttpResponse.Body?displayProperty=nameWithType allows the response body to be written with xref:System.IO.Stream:
HttpResponse.Body can be written directly or used with other APIs that write to a stream.
An alternative way to write the response body is to use the xref:Microsoft.AspNetCore.Http.HttpResponse.BodyWriter?displayProperty=nameWithType property. The BodyWriter property exposes the response body as a xref:System.IO.Pipelines.PipeWriter. This API is from I/O pipelines, and it's an advanced, high-performance way to write the response.
The writer provides direct access to the response body and manages memory on the caller's behalf. Unlike HttpResponse.Body, the write doesn't copy request data into a buffer. However, a writer is more complicated to use than a stream and writer code should be thoroughly tested.
For information on how to write content to BodyWriter, see I/O pipelines PipeWriter.
HTTP/2 and HTTP/3 support response trailers. Trailers are headers sent with the response after the response body is complete. Because trailers are sent after the response body, trailers can be added to the response at any time.
The following code sets trailers using xref:Microsoft.AspNetCore.Http.ResponseTrailerExtensions.AppendTrailer%2A:
RequestAbortedThe xref:Microsoft.AspNetCore.Http.HttpContext.RequestAborted?displayProperty=nameWithType cancellation token can be used to notify that the HTTP request has been aborted by the client or server. The cancellation token should be passed to long-running tasks so they can be canceled if the request is aborted. For example, aborting a database query or HTTP request to get data to return in the response.
The RequestAborted cancellation token doesn't need to be used for request body read operations because reads always throw immediately when the request is aborted. The RequestAborted token is also usually unnecessary when writing response bodies, because writes immediately no-op when the request is aborted.
In some cases, passing the RequestAborted token to write operations can be a convenient way to force a write loop to exit early with an xref:System.OperationCanceledException. However, it's typically better to pass the RequestAborted token into any asynchronous operations responsible for retrieving the response body content instead.
[!NOTE] Minimal APIs supports binding xref:Microsoft.AspNetCore.Http.HttpContext.RequestAborted?displayProperty=nameWithType directly to a xref:System.Threading.CancellationToken parameter.
Abort()The xref:Microsoft.AspNetCore.Http.HttpContext.Abort?displayProperty=nameWithType method can be used to abort an HTTP request from the server. Aborting the HTTP request immediately triggers the xref:Microsoft.AspNetCore.Http.HttpContext.RequestAborted?displayProperty=nameWithType cancellation token and sends a notification to the client that the server has aborted the request.
The middleware in the following example:
UserThe xref:Microsoft.AspNetCore.Http.HttpContext.User?displayProperty=nameWithType property is used to get or set the user, represented by xref:System.Security.Claims.ClaimsPrincipal, for the request. The xref:System.Security.Claims.ClaimsPrincipal is typically set by ASP.NET Core authentication.
[!NOTE] Minimal APIs supports binding xref:Microsoft.AspNetCore.Http.HttpContext.User?displayProperty=nameWithType directly to a xref:System.Security.Claims.ClaimsPrincipal parameter.
FeaturesThe xref:Microsoft.AspNetCore.Http.HttpContext.Features?displayProperty=nameWithType property provides access to the collection of feature interfaces for the current request. Since the feature collection is mutable even within the context of a request, middleware can be used to modify the collection and add support for additional features. Some advanced features are only available by accessing the associated interface through the feature collection.
The following example:
For more information about using request features and HttpContext, see xref:fundamentals/request-features.
This article primarily discusses using HttpContext in request and response flow from Blazor Web App components, Razor Pages, controllers, middleware, and so forth. Consider the following when using HttpContext outside the request and response flow:
HttpContext is NOT thread safe. Accessing it from multiple threads can result in unpredictable results, such as exceptions and data corruption.HttpContext must not be captured outside of the request flow. IHttpContextAccessor:
null if accessed outside of the request flow.HttpContext outside the request flow, copy the information inside the request flow. Be careful to copy the actual data and not just references. For example, rather than copying a reference to an IHeaderDictionary, copy the relevant header values or copy the entire dictionary key by key before leaving the request flow.IHttpContextAccessor.HttpContext in a constructor.The following sample logs GitHub branches when requested from the /branch endpoint:
The GitHub API requires two headers. The User-Agent header is added dynamically by the UserAgentHeaderHandler:
The UserAgentHeaderHandler:
In the preceding code, when the HttpContext is null, the userAgent string is set to "Unknown". If possible, HttpContext should be explicitly passed to the service. Explicitly passing in HttpContext data:
When the service must access HttpContext, it should account for the possibility of HttpContext being null when not called from a request thread.
The application also includes PeriodicBranchesLoggerService, which logs the open GitHub branches of the specified repository every 30 seconds:
PeriodicBranchesLoggerService is a hosted service, which runs outside the request and response flow. Logging from the PeriodicBranchesLoggerService has a null HttpContext. The PeriodicBranchesLoggerService was written to not depend on the HttpContext.
For more information about accessing HttpContext, see xref:fundamentals/httpcontext.