0

I'd like to have one more parameter in my api, but it's not fixed. In this case {config} can be anything like config1, config2, config1433....

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{config}/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

I already tried to get the parameter and remove it from the request uri using a delegate handler, but it doesn't work because the url has been already analyzed.

  • You don't need to do anything elaborate, it would be pretty limiting if you could only have one parameter named "id". I like to use attribute routing, it is easier to make your routes anything you want. https://docs.microsoft.com/en-us/aspnet/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2 – Crowcoder Jan 17 '18 at 20:48
  • I think it's a different case. This parameter that I want to pass is independent of any controller or action. I don't want to pass it to all controllers or all actions. – Cassio Tavares Jan 17 '18 at 21:09
  • I don't understand what you are asking. – Crowcoder Jan 17 '18 at 21:14
  • With attribute parameters I'll have decorate and read it in all my actions. And all my actions will have to receive this attribute. I want something more generic and earlier in web api stack. That's why I'm trying to use routeTemplate for that. Or, another option could be use it like a sub domain. Something like {config}.myhost.com/api/{controller}/{id} – Cassio Tavares Jan 17 '18 at 21:33
  • You know you can map more than one route template? You can map as many as you want. – Crowcoder Jan 17 '18 at 21:35
  • Yes, by I need to know the route before. In this case it is dynamic. The configuration comes from another api. And I don't know how many will exist. – Cassio Tavares Jan 17 '18 at 21:38
  • OK, now I get it. Sorry, I don't think I can help. – Crowcoder Jan 17 '18 at 21:39
  • Much more important. You tried. Thanks! – Cassio Tavares Jan 17 '18 at 21:42

1 Answers1

0

I found a solution.

First I had to inherit from DefaultHttpControllerSelector. Deriving this class allow you to customize the controller selection. In my case, it was that simple.

public class CustomControllerSelector : DefaultHttpControllerSelector
{
    private HttpConfiguration _config;

    public IHttpControllerSelector PreviousSelector { get; set; }

    public CustomControllerSelector(HttpConfiguration configuration):base(configuration)
    {
        _config = configuration;
    }

    public override HttpControllerDescriptor SelectController(HttpRequestMessage request)
    {
        var uriSegments = request.RequestUri.Segments;
        var system = uriSegments[2];

        request.RequestUri = new System.Uri(request.RequestUri.AbsoluteUri.Replace(system, ""));

        var controllerDescriptor = PreviousSelector.SelectController(request);

        return controllerDescriptor;
    }
}

Than I had to replace the default one with my customization. But I saved the previous one because I used it after the url manipulation.

var previousSelector = config.Services.GetService(typeof(IHttpControllerSelector)) as IHttpControllerSelector;
config.Services.Replace(typeof(IHttpControllerSelector), new CustomControllerSelector(config) { PreviousSelector = previousSelector});

This was my reference.

ASP.NET Web API custom IHttpControllerSelector for a single route