With the default action selector (ApiControllerActionSelector), we cannot have multiple methods which accept complex type params along with FromUri applied. For exmaple, Cmd1 and Cmd2 are two different types and have different properties. If we have Get(Cmd1 cmd) and Get(Cmd2 cmd) + the route template of "api/{controller}", we would get the ambiguity error by the ApiControllerActionSelector.
Here,you can see a repo: https://gist.github.com/3557926
To work around this problem, I wanted to customize the ApiControllerActionSelector but it's not that much customizable. I didn't wanna go and write my own stuff because ApiControllerActionSelector has some really nice featues such as caching and selection logic. So, Just to try things out, I cloned the source of ApiControllerActionSelector and created a shadow copy. Then, I go inside it and implement my own stuff there:
https://github.com/WebAPIDoodle/WebAPIDoodle/commit/f3d015dd595a6203b563c4b3c15ef308a5f86362
The customization was minor but useful IMO:
https://github.com/WebAPIDoodle/WebAPIDoodle/commit/f3d015dd595a6203b563c4b3c15ef308a5f86362#L11R131
With this action selector, we can have the ability specify action parameter through an Attribute named as UriParameteSAttribute. We just need to replace the default action selector with this one and apply the UriParametersAttribute to the action method, the specify the parameter on the attribute. Sample:
https://gist.github.com/3559725
I am not suggesting that this should be baked into the framework as it is but a solution to this problem would make it really nice.
Comments: I refactored my code a little bit and now the modification is now only one line inside the action selector's ActionSelectorCacheItem constructor. _actionParameterNames.Add( actionDescriptor, actionBinding.ParameterBindings .Where(binding => !binding.Descriptor.IsOptional && TypeHelper.IsSimpleUnderlyingType(binding.Descriptor.ParameterType) && binding.WillReadUri()) .Select(binding => binding.Descriptor.Prefix ?? binding.Descriptor.ParameterName) .Union(method.IsDefined(typeof(UriParameterAttribute)) ? method.GetCustomAttribute<UriParameterAttribute>().Parameters : Enumerable.Empty<string>(), StringComparer.OrdinalIgnoreCase).ToArray());
Here,you can see a repo: https://gist.github.com/3557926
To work around this problem, I wanted to customize the ApiControllerActionSelector but it's not that much customizable. I didn't wanna go and write my own stuff because ApiControllerActionSelector has some really nice featues such as caching and selection logic. So, Just to try things out, I cloned the source of ApiControllerActionSelector and created a shadow copy. Then, I go inside it and implement my own stuff there:
https://github.com/WebAPIDoodle/WebAPIDoodle/commit/f3d015dd595a6203b563c4b3c15ef308a5f86362
The customization was minor but useful IMO:
https://github.com/WebAPIDoodle/WebAPIDoodle/commit/f3d015dd595a6203b563c4b3c15ef308a5f86362#L11R131
With this action selector, we can have the ability specify action parameter through an Attribute named as UriParameteSAttribute. We just need to replace the default action selector with this one and apply the UriParametersAttribute to the action method, the specify the parameter on the attribute. Sample:
https://gist.github.com/3559725
I am not suggesting that this should be baked into the framework as it is but a solution to this problem would make it really nice.
Comments: I refactored my code a little bit and now the modification is now only one line inside the action selector's ActionSelectorCacheItem constructor. _actionParameterNames.Add( actionDescriptor, actionBinding.ParameterBindings .Where(binding => !binding.Descriptor.IsOptional && TypeHelper.IsSimpleUnderlyingType(binding.Descriptor.ParameterType) && binding.WillReadUri()) .Select(binding => binding.Descriptor.Prefix ?? binding.Descriptor.ParameterName) .Union(method.IsDefined(typeof(UriParameterAttribute)) ? method.GetCustomAttribute<UriParameterAttribute>().Parameters : Enumerable.Empty<string>(), StringComparer.OrdinalIgnoreCase).ToArray());