如何手动实例化控制器基于属性的路由?

时间:2018-12-21 23:44:23

标签: c# asp.net-core asp.net-core-webapi

我正在实现一个Web API,当资源不可用时,它将向客户端返回202接受。返回给客户端的URL类似于

http://host/api/v2/**thing**reqests/*guid*

我想一般地这样做,因为我有许多不同类型的资源(因此还有控制器),并且我不想重复代码。

我创建了

[AttributeUsage(AttributeTargets.Class)]
public class RelatedControllerAttribute : Attribute
{
    public Type RelatedControllerType { get; }

    public RelatedControllerAttribute(Type relatedControllerType) => RelatedControllerType = relatedControllerType;
}

像这样将其应用于主控制器

[RelatedController(typeof(ThingRequestsController))]
public class ThingsController : ApiController<ThingRequest>

这使我可以进入与请求控制器关联的路由模板。

[Route("api/v{version:apiVersion}/[controller]")]

此代码位于ThingsController的基类中

    private string GetRequestsRoute()
    {
        if (_requestsPath != null)
            return _requestsPath;

        var a = GetType().GetCustomAttribute<RelatedControllerAttribute>();
        if (a == null)
            throw new NotSupportedException();
        var routeTemplate = a.RelatedControllerType.GetCustomAttribute<RouteAttribute>().RouteTemplate;

        return _requestsPath = route.Name;
    }

这几乎使我到了那里。如何使用正确的有意义值实例化路由模板。 ASP.NET Core中内置了什么吗?我可以轻松地完成路线的[controller]部分,但是如何做到{version:ApiVersion}部分(来自ApiExplorer)呢?

1 个答案:

答案 0 :(得分:0)

我最终结束了。感觉有些欠佳,但是可以。

    private string GetRequestsRoute(string requestsRoot)
    {
        if (_requestsPath != null)
            return _requestsPath;

        var relatedControllerAttribute = GetType().GetCustomAttribute<RelatedControllerAttribute>();
        if (relatedControllerAttribute  == null)
            throw new NotSupportedException($"The {GetType().Name} must have a ${typeof(RelatedControllerAttribute).Name}");

        var apiExplorerSettingsAttribute = relatedControllerAttribute.RelatedControllerType.GetCustomAttribute<ApiExplorerSettingsAttribute>();
        if (apiExplorerSettingsAttribute == null)
            throw new NotSupportedException($"The {relatedControllerAttribute.RelatedControllerType.Name} must have a ${typeof(ApiExplorerSettingsAttribute).Name}");

        var routeAttribute = relatedControllerAttribute.RelatedControllerType.GetCustomAttribute<RouteAttribute>();
        if (routeAttribute == null)
            throw new NotSupportedException($"The {relatedControllerAttribute.RelatedControllerType.Name} must have a ${typeof(RouteAttribute).Name}");

        return _requestsPath = routeAttribute.Template
            .Replace(
                "[controller]",
                relatedControllerAttribute.RelatedControllerType.Name.Replace("Controller", ""))
            .Replace(
                "{version:apiVersion}",
                apiExplorerSettingsAttribute.GroupName.Replace("v", ""))
            .ToLowerInvariant();
    }