dotnet / aspnetcore Public
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
Provide an option on FromRouteAttribute that allows decoding the value being bound #11544
Comments
Thanks for contacting us, @SchroterQuentin. |
The problem exist on [HttpGet] [HttpPost] [HttpPut] etc. Is there a way to handle all this problems in one area ? Or do we have to add this options on all this attributes ? I'm actually not understanding how would work this option ? |
Also see aspnet/Mvc#6388 The hosts partially decodes the percent encoding and explicitly skips decoding %2F here:
The main problem is Routing or MVC model binding cannot reliably decode the partially decoded segment. Ideally the server should not do any decoding especially not partial. (Full decoding is not possible since it would introduce new segments.) If the server behavior is not allowed to change (even behind a compatibility flag) then the router middleware could be modified to use the raw request url from IHttpRequestFetaure.RawTarget (which is not yet decoded) to get proper encoded tokens then decode as needed. A possible workaround: inject a middleware before routing takes place that restores the original undecoded path from IHttpRequestFeature.RawTarget then in another middleware after routing decode the RouteData tokens. |
As part of doing this, ensure binding to non-string values that require decoded values work. See #11134 |
Can we get an update on this? I just spent half an hour debugging my API before I found out that Route parameters are not URL decoded by default. |
Yeah, this behaviour is pretty weird. If you can't fix it then this FromRouteAttribute option would be a good compromise for me. Or perhaps provide an example implementation of the middleware suggested by https://github.com/Eilon in aspnet/Mvc#6388 |
I see that this bug lives since at least 2017 and there is not even a workaround about it. |
We will consider fixing this in the upcoming 5.0 release. That said, the plan is to not have this decoding on by default - you explicitly would have to opt-in to this behavior. For current releases, you should be able to unblock yourselves by explicitly url decoding values in your action that you know require to be decoded. |
We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process. |
I face the same issue when passing encoded URI as part of route. In this case, |
I faced the same issue when passing encoded URI as query parameters. I tried every solution I found on google, but no one work. so I started to try myself and I found a solution. I explicit the get set. In you example public class GetRightsRequest In my case instead [FromRoute] I use [FromQuery] but I think it will work. |
Hi devs, please advise if not dealing the route cause of this issue, please provide a proper workaround this is not that small of a thing, the DOTNET core FW should be working according to REST standards this partial escaping is really a wired behavior : |
A workaround is to provide your own model binder and provider: // Startup.cs : ConfigureServices
services.AddMvcCore(options =>
{
options.ModelBinderProviders.Insert(0, new DecodePathStringsBinderProvider());
});
public class DecodePathStringsBinderProvider : IModelBinderProvider
{
public IModelBinder? GetBinder(ModelBinderProviderContext context)
{
return context.Metadata.ModelType == typeof(string) && context.BindingInfo.BindingSource == BindingSource.Path /* or Route, or whatever you want */ ? new BinderTypeModelBinder(typeof(DecodePathStringsBinder)) : null;
}
}
public class DecodePathStringsBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
{
throw new ArgumentNullException(nameof(bindingContext));
}
var modelName = bindingContext.ModelName;
// Try to fetch the value of the argument by name
var valueProviderResult = bindingContext.ValueProvider.GetValue(modelName);
if (valueProviderResult == ValueProviderResult.None)
{
return Task.CompletedTask;
}
var value = valueProviderResult.FirstValue;
var urlDecode = HttpUtility.UrlDecode(value);
bindingContext.ModelState.SetModelValue(modelName, urlDecode, value);
bindingContext.Result = ModelBindingResult.Success(urlDecode);
return Task.CompletedTask;
}
}
|
Thanks for contacting us. We're moving this issue to the |
What am I missing? I can't understand that this isn't fixable in 6 years. It is very easy:
Examples (input string in unencoded form):
THERE IS NO SOLUTION FOR THIS PROBLEM POSSIBLE Is there any reason why route parameters should not be fully URL decoded, by default? I can think of none. And if there is, is it as devastating as the problem above? In short route parameter can not be used in asp .net core (unless you know all possible values in advance....) |
For me, this only happens when the controller inherits from ControllerBase class. The workaround for me is that instead of ControllerBase, I inherit the controller from the Controller class. |
@asprna I can not confirm this, for me it happens both with Controller and ControllerBase as base class. (Maybe this depends on the .net core version, after all this bug could have been fixed in 3.1) |
@Nils-Berghs I am currently using .net core 3.1 |
@Nils-Berghs Actually you are right. The actual workaround is to get the value from the query string.
|
The rights of my users are at
/api/admin/users/{userId}/rights
And my controller is as simple as
or
The problem I have is that, the userIds of my users may contains a
/
which is encoded to%2F
in the Uri. But userId doesn't decode%2F
so my string contains%2F
. It's fine for me, I can deal with that.But the userIds of my users may contains a😲
+
which is encoded to%2B
in the Uri. And now, the userId decode the%2B
to+
Currently, I can't use
. My only actual solution is to replace
WebUtility.UrlDecode(userId)
becauseuserId
may contains a+
which would be send as%2B
decoded as+
and finally to%2F
to/
which is ugly and does not solve all the possibility :%252F
I saw a recommandation to use
[FromQuery]
instead of[FromRoute]
but it's obvious that if both exist, it's because they have semantic difference.It seems that's not the first time the problem appears : aspnet/Mvc#4599, #2655, #4445 and I'd like to know if it's on the roadmap to change this behavior or not.
Could you please this time consider this bug ? I'd be happy to help.
The text was updated successfully, but these errors were encountered: