从HttpContext获取控制器名称dotnet 6

3

我想在中间件中获取控制器名称。有很多答案使用如下的RequestContextRouteData

string controllerName = context.Request.RouteValues["controller"].ToString();

我尝试了这个方法,但它总是返回 null,有没有在 .NET 6 中实现的方法?
更新:.NET 版本为 6.0.100-rc.1.21458.32
我的 Program.cs:
var builder = WebApplication.CreateBuilder(args);

var configuration = new ConfigurationBuilder()
    .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
    .AddEnvironmentVariables()
    .Build();

// Add services to the container.

builder.Services.AddControllers();
builder.Services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new() { Title = "RMS.Admin.Api", Version = "v1" });
});

builder.Services.AddCoreServices(configuration);

var app = builder.Build();

if (builder.Environment.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
    app.UseSwagger();
    app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "RMS.Admin.Api v1"));
}

// Configure the HTTP request pipeline.



app.UseHttpsRedirection();

app.UseAuthorization();

app.UseElmah();

app.MapControllers();

app.UseAuditLogMiddleware();

app.UseErrorLoggingMiddleware();

app.Run();

中间件的调用方法:

        public async Task Invoke(HttpContext httpContext, IUserContext userContext, IAuditLogContract auditLogContract)
        {
            System.Console.WriteLine(httpContext.GetEndpoint()?.Metadata.GetMetadata<ControllerActionDescriptor>());
            auditLogContract.Add(new AuditLog
            {
                LoginStatus = (userContext.Id == "") ? false : true,
                Controller = httpContext.Request.RouteValues["controller"]?.ToString(),
// More code here
            });

            await this.next(httpContext);
        }

1
请帮我们一个忙,把您的program.cs/Startup.cs代码(其中设置了您的中间件)复制粘贴过来,这样我们就可以重现您的问题。如果我们尝试追踪您的步骤,运行dotnet --version也是个好主意。这样我们就可以使用相同的版本进行操作。 - Marco
现在我们需要您的中间件代码。我猜它是Audit和/ErrorLogMiddleware,但我们需要确认一下。 - Marco
@Marco 添加了 Invoke 方法。 - Amol Borkar
2个回答

4

我刚刚测试了这个,它在 .Net 6 下确实可以工作。请注意,中间件的顺序很重要,如果你的中间件在 app.UseRouting() 前被调用,那么你的 RouteValues 将为 null。

应用程序代码:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllersWithViews();

var app = builder.Build();

app.UseDeveloperExceptionPage();

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

app.UseRouting();
//if you need your route values this is the earliest point you can inject your middleware into the pipeline. 

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Use(async (context, next) =>
{
   var controller = context.Request.RouteValues["controller"]?.ToString();

   await next();
});

app.Run();

测试于

➜ dotnet --version
6.0.100-preview.7.21379.14

我在我的中间件中传递了一个HttpContext,并希望在Invoke方法中获取控制器。为什么我需要使用app.Use()? - Amol Borkar
使用的代码是中间件,而不仅仅是一个类。你可以在中间件类中编写相同的代码。 - Michael Mairegger
你不需要使用它。我只是有点懒,将中间件内联而不是为其创建专门的类。 - Marco
我刚刚检查了项目的 Program.cs 文件,发现我们没有在任何地方使用 app.UseRouting。也许这就是为什么我收到了 null 的原因,有什么解决方案吗? - Amol Borkar
你的模板基于什么?MVC、Web Api 还是 Razor Pages? - Marco
Web API,我相信。 - Amol Borkar

0
除了Marco的答案外,以下解决方案也适用。如果您需要有关控制器类型的更多信息,而不仅仅是名称,例如控制器类的TypeInfo,调用操作的MethodInfo等...
app.Use(async (e, next) =>
{
    var controllerActionDescriptor = e.GetEndpoint()?.Metadata.GetMetadata<ControllerActionDescriptor>();
    await next();
});

注意:这段代码必须放在app.UseRouting之后,否则GetEndpoint()会返回null


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接