用于区域控制器的ASP.NET Core单独中间件

时间:2017-01-10 20:27:54

标签: asp.net asp.net-core url-routing

我正在构建一个原型,我在同一个项目中托管我的ASP.NET Core网站(标准控制器/视图等)和API。

我希望使用以下路线方案:

  • blah.com/xxxx - 网站控制器和操作。
  • blah.com/api/xxxx - api控制器和操作。

到目前为止,我的方法是查看区域,下面的路径配置完美运行:

app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "areaDefault",
        template: "{area:exists}/{controller=Values}/{action=Index}");

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

现在我想扩展它以在访问API时使用一组中间件,在访问网站时使用另一组中间件。实际上,这是在区域之间使用不同的认证设置。 Google-fu引导我使用IApplicationBuilder.Map方法,这就是我的问题所在。

下面的配置适用于默认路由,执行Home / Index但是/ api后面的任何内容都返回404.

// TODO: Add common middleware.

app.Map("/api", builder =>
{
    // TODO: Add api specific middleware.

    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "apiDefault",
            template: "api/{controller=Values}/{action=Index}");
    });
});

// TODO: Add website specific middleware.

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

我尝试过没有成功的路线是:

  • foo.com/api
  • foo.com/api/values
  • foo.com/api/values/index
  • foo.com/api/api
  • foo.com/api/api/values
  • foo.com/api/api/values/index

ValuesController位于Regions / Api / Controllers文件夹下,定义为:

[Area("api")]
public class ValuesController : Controller
{
    public IActionResult Index()
    {
        return Json(new { test = 1 });
    }
}

可以在此处找到重现此内容的完整来源:https://github.com/AntSwift/ApiRouteTest

我是否正朝着正确的道路前进,是否有一些明显的我遗失或者是我试图根本不可能的事情。

2 个答案:

答案 0 :(得分:2)

我建议采取不同的做法,不要将它们混合在一起。只需创建您的api区域或以您想要的方式使用api路由。然后创建一个中间件并将其命名为" ApiAuthenticationMiddleware"。把它放在配置管道的顶部。在该中间件中查看httpcontext中的不同属性。 httpcontext中有很多有用的值。在你的情况下你可以使用" path"找出要求的地方。

如果路径有" / api /"在里面。这意味着它会进入你的api。否则它将转到您的普通控制器。在这种情况下,您应该短路到管道中的下一步。

再次在您的情况下,您可以在中间件中使用以下代码段作为示例。你应该按照你想要的方式改变它:

    public async Task Invoke(HttpContext httpContext, YourDbContext dbContext)
    {
        string requestPath = httpContext.Request.Path.Value;

        if(!requestPath.Contains("/api/"))
            await _next.Invoke(httpContext);

        string authHeader = httpContext.Request.Headers["Authorization"];
        if (authHeader != null && authHeader.StartsWith("Basic"))
        {
            //Extract credentials
            // other stuff

            // example when no authorization header exists and want to reject.
            httpContext.Response.StatusCode = 401; //Unauthorized
            return;


        // Call the next delegate/middleware in the pipeline
        await _next.Invoke(httpContext);
        }
    }

答案 1 :(得分:0)

选中此处,在地图部分中将app.UseMvc替换为builder.UseMvc

app.Map("/api", builder =>
{
    // TODO: Add api specific middleware.

    app.UseMvc(routes =>   // should be builder.UseMvc(routes
    {
        routes.MapRoute(
            name: "apiDefault",
            template: "api/{controller=Values}/{action=Index}");
    });
});