Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.Net Core Middleware - Getting Form Data from Request

In a .NET Core Web Application I am using middleware (app.UseMyMiddleware) to add some logging on each request:

        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);
            }
        }

This all works fine and I can grab most of what I need from the request but what I need next is the Form Data on a POST method.

context.Request.Form is an available option but when debugging I hover over it and see "The function evaluation requires all thread to run". If I try to use it the application just hangs.

What do I need to do to access Request.Form or is there an alternative property with POST data that I'm not seeing?

like image 610
mwade Avatar asked May 09 '19 08:05

mwade


People also ask

How does middleware work in NET Core?

Middleware are software components that are assembled into an application pipeline to handle requests and responses. Each component chooses whether to pass the request on to the next component in the pipeline, and can perform certain actions before and after the next component is invoked in the pipeline.

What is middleware in .NET Core and how is it injected in the request pipeline?

Middleware is software that's assembled into an app pipeline to handle requests and responses. Each component: Chooses whether to pass the request to the next component in the pipeline. Can perform work before and after the next component in the pipeline.


1 Answers

You can create a separate middleware rather than an inline one and then call the HitDetails.StoreHitDetails from there.

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>();
    }
}

That way you can continue using app.UseMyMiddleware(); and you don't have to run it using Task.Run as you mentioned.

Or you can just try calling HitDetails.StoreHitDetails(context) without wrapping it in Task.Run

Edited

Check if your Request has a correct content type:

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"];
 }
like image 167
Shahzad Hassan Avatar answered Oct 19 '22 14:10

Shahzad Hassan