1

I have my API route attribute class like this

public class MyRouteAttribute : RouteAttribute
{
    private const string BaseRoute = "api/default";
    private const string PrefixRouteBase = BaseRoute + "/";
    public MyRouteAttribute() : base(BaseRoute)
    {

    }
    public MyRouteAttribute(string route):
        base(string.IsNullOrEmpty(route) ?
            BaseRoute : PrefixRouteBase + route)
        {

        }

}

And it is used in controller like this

[MyRoute]
public class MyController : Controller
{
    .....
}

How do I pass IOptions to MyRoute if I have to make the route configurable?

For example, if I do this:

public class MyRouteAttribute : RouteAttribute
{
    private const string BaseRoute = "api/default";

    public MyRouteAttribute(IOptions<ApiRouteBaseConfiguration> routeOptions) : 
        base(routeOptions.Value.Url)
    {

    }

    public MyRouteAttribute(IOptions<ApiRouteBaseConfiguration> routeOptions, string route):
        base(string.IsNullOrEmpty(route) ? (routeOptions.Value.Url: $"{routeOptions.Value.Url}/" + route)
    {

    }
}

Then I get error here [MyRoute] asking me to pass IOptions.

How do I access configuration in MyRoute attribute

Marc LaFleur
  • 31,987
  • 4
  • 37
  • 63
Esen
  • 973
  • 1
  • 21
  • 47

1 Answers1

2

Attribute instances are created by CLR when attributes are requested from Reflection routines. You have no way to force instantiation of attributes via any DI container.

I see two possible approaches to workaround your challenge. Both of them allow you to have configurable attribute, however configuration is set not via attribute constructor.

  1. The simpler way is to set configuration through static property loaded on application startup:

    public class MyRouteAttribute : RouteAttribute
    {
        public static ApiRouteBaseConfiguration RouteConfiguration { get; } = new ApiRouteBaseConfiguration();
    
        public MyRouteAttribute() :
            base(RouteConfiguration.Url)
        {
        }
    
        public MyRouteAttribute(string route) :
            base(string.IsNullOrEmpty(route) ? RouteConfiguration.Url : $"{RouteConfiguration.Url}/" + route)
        {
        }
    }
    

    Configuration (Configuration section is named "Routing" here):

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();
    
        Configuration.Bind("Routing", MyRouteAttribute.RouteConfiguration);
    }
    

    Well, this solution is not perfect because of static property usage. However it's quite simple and should do the trick.

  2. The second possible approach - use Property Injection pattern for attribute configuration and set it in custom implementation of IApplicationModelProvider. Such approach is described in this answer, I will not duplicated the code here.

CodeFuller
  • 30,317
  • 3
  • 63
  • 79
  • Thank you, first approach is quick solution for now, I'll review second solution and work on it and compare the performance to decide which one to take. – Esen Apr 10 '18 at 14:50