Создайте собственный атрибут маршрута в ASP.NET Core 2 - PullRequest
0 голосов
/ 09 ноября 2018

У нас есть несколько конечных точек, где мы хотели бы сделать одно и то же для каждой из них: Зарегистрируйте их как маршрут и убедитесь, что пользователь имеет к ним доступ. Очень сжато, наша проблема может быть сведена к следующему:

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

Как вы можете сказать, это очень упрощено, но я надеюсь, что намерение достигнуто. Кажется, что трудной частью является регистрация маршрута без использования атрибута маршрута по умолчанию.

Ответы [ 2 ]

0 голосов
/ 15 ноября 2018

Вообще говоря, вы не можете «объединять» атрибуты, потому что атрибуты не выполняют код. Атрибуты являются только маркерами. Как "этот метод отмечен красным и синим". Затем появится другой код: один ищет все красные метки и что-то делает, а другой ищет все синие метки и делает что-то еще. Создание пурпурной метки путем слияния красного и синего просто запутает код, ищущий разметку, потому что фиолетовый не является ни красным, ни синим.

Тем не менее, AOP (аспектно-ориентированное программирование) доступно от третьих лиц для C # и означает атрибуты (называемые аспектами, потому что они делают больше, чем обычные атрибуты маркера) может выполнять код.

Вы можете написать аспект, который украшает метод, в котором он находится, с нужными вам атрибутами, так что вы можете написать его один раз (и протестировать), а затем установить его для каждого метода, не беспокоясь о том, чтобы забыть атрибут или установить его. неправильно.

Существует несколько провайдеров AOP для C #, наиболее популярным из которых является PostSharp. Вы можете увидеть, как написать аспект, который добавляет атрибуты к классу или методу во время компиляции с PostSharp здесь .

0 голосов
/ 15 ноября 2018

Этого можно добиться с помощью пользовательской реализации IActionModelConvention. Официальная документация объясняет концепцию соглашения модели действия: Работа с моделью приложения в ASP.NET Core - Соглашения . Вкратце, реализуя 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, который просто добавляет новый SelectorModel для каждого routeTemplate (как я его назвал), каждый из которых ограничен HTTP GET запросы.

...