在ASP.NET Core 2中创建自定义路由属性

时间:2018-11-09 12:40:59

标签: c# asp.net-core asp.net-core-mvc asp.net-core-2.1

我们有一堆端点,我们希望它们对每个端点执行完全相同的操作: 将它们注册为路由,并验证用户是否有权访问它们。非常精打细算,我们的问题可以归结为我们遇到这样的事情:

[HttpGet, Route(EntityId.First)]
[HttpGet, Route(EntityId.Second)]
[VerifyAccessFilter(EntityId.First, EntityId.Second)]
public async Task<IActionResult> Endpoint()
{   
    return Ok();
}

但更希望是这样的:

[RouteAndVerify(EntityId.First, EntityId.Second)]
public async Task<IActionResult> Endpoint()
{   
    return Ok();
}

您可以说这很简单,但是我希望这个意图能够传播。 困难的部分似乎是在不使用默认Route-attribute的情况下注册路由。

2 个答案:

答案 0 :(得分:1)

您可以通过自定义IActionModelConvention实现来实现。官方文档解释了动作模型约定的概念:Work with the application model in ASP.NET Core - Conventions。简而言之,通过实现IActionModelConvention,您可以更改应用程序模型,并在运行时为操作添加过滤器,路由等。

最好通过一个示例实现来对此进行解释,如下所示。当您想将现有的MVC过滤器与配置动作路由的功能结合在一起时,下面的实现同时实现IResourceFilter(可以是您使用的任何过滤器类型)和IActionModelConvention

public class VerifyAccessFilterAttribute : Attribute, IActionModelConvention, IResourceFilter
{
    public VerifyAccessFilterAttribute(params string[] routeTemplates)
    {
        RouteTemplates = routeTemplates;
    }

    public string[] RouteTemplates { get; set; }

    public void Apply(ActionModel actionModel)
    {
        actionModel.Selectors.Clear();

        foreach (var routeTemplate in RouteTemplates)
        {
            actionModel.Selectors.Add(new SelectorModel
            {
                AttributeRouteModel = new AttributeRouteModel { Template = routeTemplate },
                ActionConstraints = { new HttpMethodActionConstraint(new[] { "GET" }) }
            });
        }
    }

    public void OnResourceExecuting(ResourceExecutingContext ctx) { ... }

    public void OnResourceExecuted(ResourceExecutedContext ctx) { ... }
}

在此示例中,所有内容都与Apply方法有关,该方法只是为每个routeTemplate(如我所命名的)添加一个新的SelectorModel,每个方法都被限制为HTTP GET请求。

答案 1 :(得分:0)

通常来说,您不能“合并”属性,因为属性不会执行代码。属性只是标记。就像“此方法标记为红色和蓝色”。然后将出现其他代码,一个代码寻找所有红色标记并执行某项操作,另一个代码寻找所有蓝色标记并执行其他操作。通过合并红色和蓝色来构建紫色标记只会混淆寻找标记的代码,因为紫色既不是红色也不是蓝色。

但是,第三方可以使用C#的AOP(面向方面​​的编程),并且意味着属性(称为方面,因为它们比常规标记属性做得更多)可以执行代码。

您可以编写一个方面,用所需的属性来装饰它所位于的方法,因此您可以编写一次(并对其进行测试),然后可以在每个方法上对其进行设置,而不必担心忘记属性或对其进行设置错误的。

C#有多个AOP提供程序,其中最受欢迎的似乎是PostSharp。您可以看到如何编写在PostSharp here编译时将属性添加到类或方法的方面。