ApiExplorer cannot figure out the correct URI Parameters if I plug in a custom IHttpActionSelector. A repro application is available here: https://github.com/tugberkugurlu/ASPNETWebAPISamples/tree/58b5b2f1b5d60051d1058a5ebea725bfbee2f451/v2/AttributeRoutingSample
Here is an example:
I have the following controller:
public class ProductsController : ApiController
{
public Task<IEnumerable<ProductDto>> GetProducts(PaginatedRequestCommand cmd)
{
// Doing some stuff...
}
public Task<IEnumerable<ProductDto>> GetProducts(ProductsByStatusPaginatedRequestCommand cmd)
{
// Doing some stuff...
}
[ResponseType(typeof(ProductDto))]
public IHttpActionResult GetProduct(int id)
{
// Doing some stuff...
}
}
Here is the Method parameters I used:
public interface IRequestCommand
{
}
public class PaginatedRequestCommand : IRequestCommand
{
public int Skip { get; set; }
public int Take { get; set; }
}
public class ProductsByStatusPaginatedRequestCommand : PaginatedRequestCommand
{
public string Status { get; set; }
}
I also have the following configuration to bind IRequestCommand objects from the URI:
// Any complex type parameter which is assignable From
// IRequestCommand will be bound from the URI.
config.ParameterBindingRules.Insert(0, descriptor =>
typeof(IRequestCommand).IsAssignableFrom(descriptor.ParameterType)
? new FromUriAttribute().GetBinding(descriptor) : null);
Here is my route:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
With this setup, I should get ambiguous action exception if I send a GEt request to /Products?skip=1&take=10. However, I will use my own action selector to make this work correctly. What it will do is to take complex type parameters (only one level down inside the object graph) into consideration while performing the action selection.
// Replace the default action selector so that we can use
// complex types as URI parameters.
config.Services.Replace(typeof(IHttpActionSelector), new ComplexTypeAwareActionSelector());
Now, I can hit both of the following endpoints:
> GET /Products?skip=1&take=10
> GET /Products?skip=1&take=10&status=onsale
However, API Explorer will ignore these two very valid endpoints and the `private static TryExpandUriParameters` method inside the API explorer causes this misbehaviour.
Comments: This is indeed an unsupported scenario. We are not planning any work at the moment to expand the support in this area.
Here is an example:
I have the following controller:
public class ProductsController : ApiController
{
public Task<IEnumerable<ProductDto>> GetProducts(PaginatedRequestCommand cmd)
{
// Doing some stuff...
}
public Task<IEnumerable<ProductDto>> GetProducts(ProductsByStatusPaginatedRequestCommand cmd)
{
// Doing some stuff...
}
[ResponseType(typeof(ProductDto))]
public IHttpActionResult GetProduct(int id)
{
// Doing some stuff...
}
}
Here is the Method parameters I used:
public interface IRequestCommand
{
}
public class PaginatedRequestCommand : IRequestCommand
{
public int Skip { get; set; }
public int Take { get; set; }
}
public class ProductsByStatusPaginatedRequestCommand : PaginatedRequestCommand
{
public string Status { get; set; }
}
I also have the following configuration to bind IRequestCommand objects from the URI:
// Any complex type parameter which is assignable From
// IRequestCommand will be bound from the URI.
config.ParameterBindingRules.Insert(0, descriptor =>
typeof(IRequestCommand).IsAssignableFrom(descriptor.ParameterType)
? new FromUriAttribute().GetBinding(descriptor) : null);
Here is my route:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
With this setup, I should get ambiguous action exception if I send a GEt request to /Products?skip=1&take=10. However, I will use my own action selector to make this work correctly. What it will do is to take complex type parameters (only one level down inside the object graph) into consideration while performing the action selection.
// Replace the default action selector so that we can use
// complex types as URI parameters.
config.Services.Replace(typeof(IHttpActionSelector), new ComplexTypeAwareActionSelector());
Now, I can hit both of the following endpoints:
> GET /Products?skip=1&take=10
> GET /Products?skip=1&take=10&status=onsale
However, API Explorer will ignore these two very valid endpoints and the `private static TryExpandUriParameters` method inside the API explorer causes this misbehaviour.
Comments: This is indeed an unsupported scenario. We are not planning any work at the moment to expand the support in this area.