404 not found 在将 Asp.net Core Middleware 与 .map 一起使用时获取响应

404 not found Gets response when using Asp.net Core Middleware with .map

下面是代码片段,我在其中编写了一个中间件,它接收 api 请求并验证它并发送响应。

但是当请求有效时它不会调用 API ,它会显示 404 Not Found 错误。

Middleware code snippet

    // You may need to install the Microsoft.AspNetCore.Http.Abstractions package into your project
public class ApiKeyValidatorsMiddleware
{
    private readonly RequestDelegate _next;
    IValidateRequest _IValidateRequest { get; set; }

    public ApiKeyValidatorsMiddleware(RequestDelegate next , IValidateRequest ivalidaterequest)
    {
        _next = next;
        _IValidateRequest = ivalidaterequest;
    }

    public async Task Invoke(HttpContext httpContext)
    {
        try
        {
            var queryString = httpContext.Request.Query;
            StringValues keyvalue;
            queryString.TryGetValue("key", out keyvalue);



            if (httpContext.Request.Method != "POST")
            {
                httpContext.Response.StatusCode = 405; //Method Not Allowed               
                await httpContext.Response.WriteAsync("Method Not Allowed");
                return;
            }

            if (keyvalue.Count == 0)
            {
                httpContext.Response.StatusCode = 400; //Bad Request                
                await httpContext.Response.WriteAsync("API Key is missing");
                return;
            }
            else
            {
                var serviceName = httpContext.Request.Path.Value.Replace(@"/", string.Empty);

                if (!_IValidateRequest.ValidateKeys(keyvalue) && !_IValidateRequest.IsValidServiceRequest(keyvalue, serviceName))
                {
                    httpContext.Response.StatusCode = 401; //UnAuthorized
                    await httpContext.Response.WriteAsync("Invalid User Key");
                    return;
                }
            }

            await _next.Invoke(httpContext);
        }
        catch (Exception)
        {
            throw;
        }
    }
}

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

Startup

 public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseBrowserLink();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
        }
        app.UseStaticFiles();
        app.UseSession();

        //Middleware Call
        app.Map("/api", appBuilder => appBuilder.UseMiddleware<ApiKeyValidatorsMiddleware>());

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "Servicedefault",
                template: "{controller=Login}/{action=Login}/{ServiceID}/{ServiceName}");

            routes.MapRoute(
                name: "default",
                template: "{controller=Login}/{action=Login}/{id?}");

        });
    }

Controller Codesnippet

很简单API,没有任何身份验证属性。

    [Route("api/[controller]")]
public class MoviesAPIController : Controller
{
    IMovies _IMovies;
    public MoviesAPIController(IMovies imovies)
    {
        _IMovies = imovies;
    }

    // GET: api/values
    [HttpGet]
    public IEnumerable<string> Get()
    {
        return new string[] { "value1", "value2" };
    }

    // GET api/values/5
    [HttpGet("{id}")]
    public string Get(int id)
    {
        return "value";
    }

    // POST api/values
    [HttpPost]
    public List<MoviesTB> Post([FromQuery]string key)
    {
        return _IMovies.GetMusicStore();
    }

Output

根据documentation

Map* extensions are used as a convention for branching the pipeline. Map branches the request pipeline based on matches of the given request path. If the request path starts with the given path, the branch is executed.

你需要像这样注册你的中间件

app.UseMiddleware<ApiKeyValidatorsMiddleware>();

然后在中间件中检查它是否是 API 调用。

httpContext.Request.Path.StartsWithSegments("/api")

中间件代码

// You may need to install the Microsoft.AspNetCore.Http.Abstractions package into your project
    public class ApiKeyValidatorsMiddleware
    {
        private readonly RequestDelegate _next;
        IValidateRequest _IValidateRequest { get; set; }

        public ApiKeyValidatorsMiddleware(RequestDelegate next, IValidateRequest ivalidaterequest)
        {
            _next = next;
            _IValidateRequest = ivalidaterequest;
        }

        public async Task Invoke(HttpContext httpContext)
        {
            try
            {
                if (httpContext.Request.Path.StartsWithSegments("/api"))
                {

                    var queryString = httpContext.Request.Query;
                    StringValues keyvalue;
                    queryString.TryGetValue("key", out keyvalue);



                    if (httpContext.Request.Method != "POST")
                    {
                        httpContext.Response.StatusCode = 405; //Method Not Allowed               
                        await httpContext.Response.WriteAsync("Method Not Allowed");
                        return;
                    }

                    if (keyvalue.Count == 0)
                    {
                        httpContext.Response.StatusCode = 400; //Bad Request                
                        await httpContext.Response.WriteAsync("API Key is missing");
                        return;
                    }
                    else
                    {
                        var serviceName = httpContext.Request.Path.Value.Replace(@"/", string.Empty);

                        if (!_IValidateRequest.ValidateKeys(keyvalue) && !_IValidateRequest.IsValidServiceRequest(keyvalue, serviceName))
                        {
                            httpContext.Response.StatusCode = 401; //UnAuthorized
                            await httpContext.Response.WriteAsync("Invalid User Key");
                            return;
                        }
                    }

                }
                await _next.Invoke(httpContext);

            }
            catch (Exception)
            {
                throw;
            }
        }
    }

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