Trying to implement Microsoft.AspNetCore.SystemWebAdapters between a ASP.NET MVC and ASP.NET Core MVC site

Viewed 91

We are trying to use the Microsoft.AspNetCore.SystemWebAdapters to implement a incremental move from a our existing ASP.NET MVC site to a ASP.NET Core MVC site. https://devblogs.microsoft.com/dotnet/incremental-asp-net-to-asp-net-core-migration/

After following the various guides and example projects supplied by MS I am hitting an error generated by a YARP protocol method which is called by the following method in the SystemWebAdapters:

public Task InvokeAsync(HttpContext context) => context.GetEndpoint()?.Metadata.GetMetadata() is { IsDisabled: false } ? SetUserAsync(context) : _next(context);

The follow exception is raised:

ArgumentException: Invalid destination prefix. (Parameter 'destinationPrefix')

Yarp.ReverseProxy.Forwarder.HttpForwarder.CreateRequestMessageAsync(HttpContext context, string destinationPrefix, HttpTransformer transformer, ForwarderRequestConfig requestConfig, bool isStreamingRequest, ActivityCancellationTokenSource activityToken) Yarp.ReverseProxy.Forwarder.HttpForwarder.SendAsync(HttpContext context, string destinationPrefix, HttpMessageInvoker httpClient, ForwarderRequestConfig requestConfig, HttpTransformer transformer) Yarp.ReverseProxy.Forwarder.ForwarderMiddleware.Invoke(HttpContext context) Yarp.ReverseProxy.Health.PassiveHealthCheckMiddleware.Invoke(HttpContext context) Microsoft.AspNetCore.Routing.EndpointMiddleware.g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger) Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context) Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context) Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

Code

This is the code in the program.cs in the Core site, I'm not using SSL at the moment:

using System.Security.Claims;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.SystemWebAdapters;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddReverseProxy().LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"));

// These must match the data protection settings in MvcApp Startup.Auth.cs for cookie sharing to work
var sharedApplicationName = "CCM";
builder.Services.AddDataProtection()
    .PersistKeysToFileSystem(new DirectoryInfo(Path.Combine(Path.GetTempPath(), "sharedkeys", sharedApplicationName)))
    .SetApplicationName(sharedApplicationName);

builder.Services.AddAuthentication()
    .AddCookie("SharedCookie", options => options.Cookie.Name = ".AspNet.ApplicationCookie");

// Add services to the container.
builder.Services.AddControllersWithViews();
builder.Services.AddSystemWebAdapters()
    .AddRemoteAppClient(remote => remote
        .Configure(options =>
        {
            options.RemoteAppUrl = new(builder.Configuration["ReverseProxyAddress"]);
            options.ApiKey = "test-key";
        })
        .AddAuthentication(true)
        .AddSession())
    .AddJsonSessionSerializer(options => options.KnownKeys.Add("Example", typeof(Example)));

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    //app.UseExceptionHandler("/Home/Error");
    //app.UseHsts();
}

//app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.UseSystemWebAdapters();

app.MapGet("/current-principals-with-metadata", (HttpContext ctx) =>
{
    var user1 = Thread.CurrentPrincipal;
    var user2 = ClaimsPrincipal.Current;

    return "done";
}).WithMetadata(new SetThreadCurrentPrincipalAttribute(), new SingleThreadedRequestAttribute());

app.MapGet("/current-principals-no-metadata", (HttpContext ctx) =>
{
    var user1 = Thread.CurrentPrincipal;
    var user2 = ClaimsPrincipal.Current;

    return "done";
});

app.UseEndpoints(endpoints =>
{
    app.MapDefaultControllerRoute();
    // This method can be used to enable session (or read-only session) on all controllers
    //.RequireSystemWebAdapterSession();

    app.MapReverseProxy();
});

app.Run();

This is the section from the global.asax.cs:

GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
ViewEngines.Engines.Insert(0, new BillingViewEngine());
ViewEngines.Engines.Remove(ViewEngines.Engines.OfType<WebFormViewEngine>().FirstOrDefault());
LocalisationConfig.RegisterAdapters();

SystemWebAdapterConfiguration.AddSystemWebAdapters(this)
    .AddProxySupport(options => options.UseForwardedHeaders = true)
    .AddJsonSessionSerializer(options => options.KnownKeys.Add("Example", typeof(Example)))
    .AddRemoteAppServer(remote => remote
        .Configure(options => options.ApiKey = "test-key")
        .AddAuthentication()
        .AddSession());

Any pointers would be useful as I've hit a bit of a wall with it.

0 Answers
Related