-
Notifications
You must be signed in to change notification settings - Fork 704
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
HttpPut and HttpDelete template parameter names issue #106
Comments
There isn't anything particularly special about HTTP methods in routing; however, they are used to whittle down the candidates for dispatching. Based on your test script, I think the issue may be a mismatch in the media type (like #72). Your example uses only primitive strings, but you are specifying that the media type is |
OK. I think you are getting caught up in how I implemented my test rather than the actual issue. The name of the template parameter in the HttpPut route can prevent an HttpDelete from getting routed correctly. I took your suggestion and updated my code to use a class as a parameter and I modified my powershell script to pass a JSON string. I still get VersionActionSelector errors. Checkout TwoController.cs
Here is my new project Dave |
Hmmm... ok. Thanks for the follow up. I'll try to repro and diagnose this over the weekend. The action selector doesn't do anything specific with parameter names. Route constraint filtering should be the same as it always was. Out of curiosity, what happens if you remove API versioning? I'm assuming you may have already tried or started with that, but I want to make sure there isn't something already flawed with the default ASP.NET Core action selector. I had the fork the code for that class. It's possible there was an update that I don't have. |
I don't have the issue without API versioning. |
I just wanted to let you know what I've found. There is seemingly some part of the ASP.NET Core routing infrastructure that I don't understand. For
The reason it isn't working with API versioning is that the ApiVersionActionSelector assumes it will not be called again and if there are no matches, but there could be one, it returns an appropriate response (400 or 405). If there is no possible match, then it returns No closer to a solution just yet, but that's what I've found. It sounds like I may have something fundamentally incorrect about when a result should be returned in the pipeline. Odd that this only occurs in your scenario. The solution to unblock yourself is obviously make the route parameter names be the same. Regardless, I'll continue looking into this issue. It appears to be a bug on my side, I'm just not sure why yet. |
Thanks. |
Would this problem be relevant on a controller marked as ApiVersionNeutral? My problematic method looks like so:
With ApiVersioning enabled the HttpPost method produces: A A If I change the HttpPost method's name/route & update the view to reflect that it works fine. The controller & views were generated using the "Add Controller > MVC Controller with views, using EntityFramework" scaffolding option in VS2017, with the only change being I added the annotations for Attribute Routing. |
I expect the issue to remain. Regardless of whether you use explicit or implicit versioning, the ApiVersionActionSelector expects to only be called once. The selector doesn't find a match on the first pass and then short-circuits the pipeline causing the incorrect behavior. I've confirmed that if the selector just returns One of the key culprits I have found that cause this behavior is when you have two overlapping routes that only differ by route parameter constraints. In your scenario, you have such a case. You have two route definitions that only differ by |
The 1.1 RC has now been published that resolves this issue. Note that there is breaking, behavioral change for ASP.NET Core to support it. :( You'll now need to call Let me know if you run into anything, but I think 1.1 is ready. |
Hello! With the new version these two routes aren't clashing anymore, which is good! Thanks! //api/v1.0/persons/idstring But now I have the problem that it doesn't differentiate between these two routes: //api/v1.0/persons/idstring Am I doing something wrong? Or could this possible be a new bug? Thanks in advance! |
I locally updated the HelloWorldController in the "BasicSample" to match your scenario. The following routes work as expected:
Can you share more about your controller and/or configuration? Perhaps compare them to the BasicExample? I'm not able to reproduce the behavior you're seeing. |
Hey Chris! Thanks for the quick reply, sorry for the late answer! I downloaded the BasicExample project and changed the names and endpoints to reflect my project and I found something interesting. These are the routes I have:
When the example runs and I call the search endpoint first, I get the following 500 internal server error:
But, if I call the GetMultiple endpoint first and after that the Search endpoint, I get a 200 but it connects to the GetMultiple endpoint:
I hope I put enough information in my post, I can add the code of the controller to if you'd like! |
Hmm... this is an interesting edge case. On one hand, it's a regression, but on the other the route is ambiguous. Without even seeing the code, I suspect that
The router will treat the action I suspected the problem might be caused these symptoms. I'm not sure exactly how to resolve the ambiguity just yet, but I'll start looking into it. I'll create a new issue to track this and link it back. It's related to this issue, but it's really not the same thing. |
I'm now tracking this as part of #133 |
This is very similar to #72, but is not the same or it might have been the core cause of #72.
If the route templates for HttpPut and HttpDelete only have a single parameter, there is a toxic relationship between the parameter names that will cause a version error to be thrown in certain situations.
The server reports:
Microsoft.AspNetCore.Mvc.Versioning.ApiVersionActionSelector: Information: Multiple candidate actions were found, but none matched the requested service API version '1.0'. Candidate actions:
The client reports:
Good
Bad
There seems to be some kind of super/sub string issue between the names. I did all my testing on the Put call but it turns out that a relationship between the parameter names exists that will prevent the Delete route from being matched also.
Here is an example project. I started with a new .NET Framework 4.6.1 ASP.NET Core Web Application (.NET Framework) project. I pruned out unnecessary methods and includes and updated all of the Microsoft.AspNetCore packages.
https://www.dropbox.com/s/vo80iolv08fms5l/RoutingSample.zip?dl=0
I have been using a combination of Postman and the PowerShell Invoke-RestMethod to call my app.
Here is my powershell script
https://www.dropbox.com/s/eshnz68kx17bwm7/test.ps1?dl=0
The text was updated successfully, but these errors were encountered: