asp.net 核心路由特定中间件

Ind*_*Dan 2 c# asp.net-core

我正在使用 KOA 2.0 并开始测试 asp.net 核心。但是找不到处理请求/网址特定中间件的方法

在 Koa 中说,使用路由器我可以实现以下目标:

.post("/api/v1/user", Middleware1, Middleware2, RequestValidationMiddleware, SpecificAction);
.get("/api/v1/user", Middleware1, Middleware2, RequestValidationMiddleware, SpecificAction1);
.post("/api/v1/role", Middleware1, Middleware4, RequestValidationMiddleware2, SpecificAction2);
Run Code Online (Sandbox Code Playgroud)

如何用asp.net核心实现它?

尝试了以下内容:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    //app.UseApiLog();
    app.Map("/api", ApiLogApps);
    app.Map("/exlog", ExceptionLogApps);

    //app.UseMvc(routes =>
    //{
    //    routes.MapRoute(
    //                    name: "default",
    //                    template: "apilog/{controller}/{action}");
    //    routes.MapRoute(
    //                    name: "default2",
    //                    template: "exlog/{controller=Home}/{action=Index}/{id:int}");
    //});
}

private static void ApiLogApps(IApplicationBuilder app)
{
    //app.Run(() => )
    app.UseApiLog();
    app.UseMvc();
}
Run Code Online (Sandbox Code Playgroud)

在控制器中我有

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

    // GET api/values/5
    [HttpGet("test/get/{id}")]
    public string Get(int id)
    {
        return "value";
    }
}
Run Code Online (Sandbox Code Playgroud)

但我在这里迷路了。

我想要的是,我想要在中间件中处理 DataValidation - 这迫使我拥有每个 url(几乎)特定的中间件。

PS - 我知道,模型验证可以在行动中完成,但我不想要那样。

在此先感谢您的帮助 :)

itm*_*nus 10

要使用 Koa2 等中间件,您可以配置一系列中间件来构建路由:

    public IRouter BuildRouter(IApplicationBuilder applicationBuilder)
    {
        var builder = new RouteBuilder(applicationBuilder);

        // use middlewares to configure a route
        builder.MapMiddlewareGet("/api/v1/user", appBuilder => {
            // your Middleware1
            appBuilder.Use(Middleware1);
            appBuilder.Use(Middleware2);
            appBuilder.Use(RequestValidationMiddleware);
            appBuilder.Run(SpecificAction);
        });

        builder.MapMiddlewarePost("/api/v1/user", appBuilder => {
            // your Middleware1
            appBuilder.Use(Middleware1);
            appBuilder.Use(Middleware2);
            appBuilder.Use(RequestValidationMiddleware);
            appBuilder.Run(SpecificAction1);
        });
        // ....

        return builder.Build();
    }
Run Code Online (Sandbox Code Playgroud)

然后通过UseRouter(router)以下方式使用 RouterMiddleware :

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    // ...
    app.UseRouter(BuildRouter(app));
    // ...
    app.UseMvc();
}
Run Code Online (Sandbox Code Playgroud)

截图:

在此处输入图片说明

[更新]:

要与属性路由集成,只需添加如下UseMvc()代替Run()

    public IRouter BuildRouter(IApplicationBuilder applicationBuilder)
    {
        var builder = new RouteBuilder(applicationBuilder);

        // use middlewares to configure a route
        builder.MapMiddlewareGet("/api/v1/user", appBuilder => {
            appBuilder.Use(Middleware1);
            appBuilder.Use(Middleware2);
            appBuilder.Use(RequestValidationMiddleware);
            appBuilder.UseMvc();          // use a MVC here ...
        });

        builder.MapMiddlewarePost("/api/v1/user", appBuilder => {
            appBuilder.Use(Middleware1);
            appBuilder.Use(Middleware2);
            appBuilder.Use(RequestValidationMiddleware);
            appBuilder.UseMvc();
        });
        // ....

        return builder.Build();
    }
Run Code Online (Sandbox Code Playgroud)

只是为了演示, Middleware1 是一个虚拟中间件,它添加了HttpContext.Items['mw-message1']

    private Func<RequestDelegate, RequestDelegate> Middleware1 = next=> {
        return async context =>
        {
            context.Items["mw-message1"] = "mw1";
            await next(context);
        };
    };
Run Code Online (Sandbox Code Playgroud)

控制器是一个普通的控制器,它将检索HttpContext.Items["mw-messages1"]

[Route("api/v1/[controller]")]
[ApiController]
public class UserController : ControllerBase
{
    public IActionResult Index()
    {
        var x = (string)HttpContext.Items["mw-message1"];
        return new JsonResult(new {
            MW1 = x,
            Hello= "Hello",
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,当向 发出 Get 请求时/api/v1/user,最终响应是:

{"mW1":"mw1","hello":"Hello"}
Run Code Online (Sandbox Code Playgroud)

  • 请注意,这不适用于 ASP.NET Core 3.0+ 中的端点路由(因为无法在分支管道上调用“UseEndpoints”)。据我所知,这可以通过使用 `app.UseWhen(c =&gt; c.Request.Path.StartsWithSegments("/foo"), ...` 来解决,它重新加入主管道。 (2认同)