c# - .Net Core 中间件——从请求中获取表单数据

标签 c# asp.net-core asp.net-core-middleware

在 .NET Core Web 应用程序中,我使用中间件 (app.UseMyMiddleware) 为每个请求添加一些日志记录:

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler(MyMiddleware.GenericExceptionHandler);
                app.UseHsts();
            }

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

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
        public static void UseMyMiddleware(this IApplicationBuilder app)
        {
            app.Use(async (context, next) =>
            {
                await Task.Run(() => HitDetails.StoreHitDetails(context));
                await next.Invoke();
            });
        }
        public static void StoreHitDetails(HttpContext context)
        {
            var config = (IConfiguration)context.RequestServices.GetService(typeof(IConfiguration));
            var settings = new Settings(config);
            var connectionString = config.GetConnectionString("Common");
            var features = context.Features.Get<IHttpRequestFeature>();
            var url = $"{features.Scheme}://{context.Request.Host.Value}{features.RawTarget}";

            var parameters = new
            {
                SYSTEM_CODE = settings.SystemName,
                REMOTE_HOST = context.Connection.RemoteIpAddress.ToString(),
                HTTP_REFERER = context.Request.Headers["Referer"].ToString(),
                HTTP_URL = url,
                LOCAL_ADDR = context.Connection.LocalIpAddress.ToString(),
                AUTH_USER = context.User.Identity.Name
            };

            using (IDbConnection db = new SqlConnection(connectionString))
            {
                db.Query("StoreHitDetails", parameters, commandType: CommandType.StoredProcedure);
            }
        }

一切正常,我可以从请求中获取我需要的大部分内容,但接下来我需要的是 POST 方法上的表单数据。

context.Request.Form 是一个可用选项,但在调试时我将鼠标悬停在它上面并看到“函数评估需要所有线程运行”。如果我尝试使用它,应用程序就会挂起。

我需要做什么才能访问 Request.Form,或者是否有我没有看到的带有 POST 数据的替代属性?

最佳答案

您可以创建一个单独的中间件而不是内联中间件,然后从那里调用 HitDetails.StoreHitDetails

public class MyMiddleware
{
    private readonly RequestDelegate _next;

    public MyMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        HitDetails.StoreHitDetails(context);

        await _next(context);
    }
}

// Extension method used to add the middleware to the HTTP request pipeline.
public static class MiddlewareExtensions
{
    public static IApplicationBuilder UseMyMiddleware(this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<MyMiddleware>();
    }
}

这样您就可以继续使用 app.UseMyMiddleware(); 而不必像您提到的那样使用 Task.Run 来运行它。

或者您可以尝试调用 HitDetails.StoreHitDetails(context) 而无需将其包装在 Task.Run

已编辑

检查您的请求是否有正确的内容类型:

if (context.Request.HasFormContentType)
{
    IFormCollection form;
    form = context.Request.Form; // sync
    // Or
    form = await context.Request.ReadFormAsync(); // async

    string param1 = form["param1"];
    string param2 = form["param2"];
 }

关于c# - .Net Core 中间件——从请求中获取表单数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56055131/

相关文章:

asp.net-core - 在 Asp Net Core 中使用全局异常处理程序和自定义中间件

c# - ASP.NET Web API - 没有 'MediaTypeFormatter' 可用于读取类型为 'Int32' 的对象

c# - 我可以为 RabbitMQ 消费者设置明确的任务超时吗?

c# - 如何在 ASP.NET Core 2.0 web api 中添加来自 IdentityServer4 和 Auth0 的 Jwt 身份验证?

c# - ASP.Net Core 3.0 依赖注入(inject)忽略工厂方法?

angular - 如何让 CORS 与 ASP.Net Core Web API 服务器 Angular 2 客户端一起工作

c# - 防止请求 header 上的 CRLF 漏洞

c# - C#计算时差:

c# - Mvc 4 捆绑和 base64 svg 图像

asp.net-core - ASP.NET Core 应用程序进入 IdentityServer3 身份验证的无限循环