dotnet / dotnet/systemweb-adapters
Proposal: AspNetCore HttpContext via FrameworkServices
- Dominant language
- C#
- Stars
- 384
- Forks
- 76
- Avg merge
- 2h 24m
- Merged PRs (30d)
- 1
Description
## Summary
Support using an AspNetCore `HttpContext` in .Net Framework 4.8, and using AspNetCore Middleware in the .Net Framework OWIN pipeline.
## Motivation and goals
I have implemented a version of this in my company's code base and believe it would be a useful for others as well.
* Enables transitioning .Net Framework classes to an AspNetCore HttpContext.
* Allows said classes to be shared between a AspNetCore project and a Framework project without installing the adapter in the AspNetCore project.
* Allows .NET Framework to use AspNetCore's authentication with minimal modification.
## In scope
A list of major scenarios, perhaps in priority order.
* Accessing an AspNetCore HttpClient via Dependency Injection.
* Using .NET Core Middleware in an OWIN middleware pipeline.
## Out of scope
Scenarios you explicitly want to exclude.
## Risks / unknowns
How might developers misinterpret/misuse this? How might implementing it restrict us from other enhancements in the future? Also list any perf/security/correctness concerns.
* Simple Implementation of an AspNetCore HttpContext relies on `Microsoft.AspNetCore.Owin` v2.3.10
* Middleware adds an additional dependency on `Microsoft.Owin`
* Adapter must be constructed for every request or a custom `IHttpContextAccessor` must be used.
My implementation used a custom `IHttpContextAccessor`, which uses `IOwinContext.Environment`. That solves the potential issue of threading causing the context to be unavailable, but feels a bit hackey.
The OWIN middleware adapter could be considered a separate feature but is a single class which makes things like the example below possible.
## Examples
### .NET Core Cookie Authentication in .NET Framework
This is an alternative to `Microsoft.Owin.Security.Interop` using AspNetCore modules directly. Example instructions are for using EF Core (v3) for data protection.
1. Ensure the following dependencies exist in the project file:
* Microsoft.Extensions.Identity.Core
* Microsoft.AspNetCore.Identity
* Microsoft.Data.SqlClient
* Microsoft.EntityFrameworkCore (Version 3)
* Microsoft.EntityFrameworkCore.SqlServer (Version 3)
* Microsoft.Extensions.Identity.Core
2. Copy the following files from `Microsoft.AspNetCore.DataProtection.EntityFrameworkCore` to a folder in the .NET Framework project:
* DataProtectionKey.cs
* EntityFrameworkCoreDataProtectionExtensions.cs
* EntityFrameworkCoreXmlRepository.cs
* IDataProtectionKeyContext.cs
3. Create a DbContext class implementing `IDataProtectionKeyContext`
4. When configuring services use:
```cs
builder.Services.AddDbContext(optionsBuilder =>
optionsBuilder.UseSqlServer(builder.Configuration.GetConnectionString("MyDbContext"))
);
builder.Services.AddDataProtection().DisableAutomaticKeyGeneration().SetApplicationName("MyApplication").PersistKeysToDbContext();
var authenticationBuilder = builder.Services.AddAuthentication(IdentityConstants.ApplicationScheme);
authenticationBuilder.AddCookie(IdentityConstants.ApplicationScheme);
```
4. Configure the OWIN pipeline as below:
```cs
[assembly: OwinStartup(typeof(MyApp.Startup), "ConfigureOwin")]
public class Startup
{
public void ConfigureOwin(IAppBuilder app)
{
app.Use>();
app.UseStageMarker(PipelineStage.Authenticate);
}
}
```
# Detailed design
Most of the hard work can be done by using `OwinFeatureCollection` along with other default feature collections. However, there are several additional things which must be implemented.
* `ISession` backed by `HttpContextBase.Session`.
* `IHttpResponseFeature.OnCompleted` is needed by the `RequestServicesFeature`
* This could be implemented in a different way.
* `IRequestCookiesFeature` needs to be implemented with an OWIN backed `IRequestCookieCollection`
* `IResponseCookiesFeature` needs to be implemented with an OWIN backed `IResponseCookieCollection`
I toyed with creating the individual features based on `HttpContext.Current` and the associated Worker, but this is much simpler of an approach.
I based the middleware adapter design on `Microsoft.AspNetCore.Authentication.AuthenticationMiddleware`.
Contributor guide
Assessment
This issue has not been assessed yet.