Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Decode string with plus sign

Using ASP.NET Core I am receiving the following token (simplified):

String token = "Z%2F3+3Q==";

The / is encoded using %2F. I received the token from a URL called on the client using Angular.

I tried to decode the token using the following:

HttpUtility.UrlDecode(token)

Or

WebUtility.UrlDecode(token)

In both cases %2F is replaced by /, which I want, but the + is replaced by a space, which I do not want.

How do I decode the string?

Update

The client application is sending the token encoded:

Z%2F3%2B3Q%3D%3D;

But, somehow, it seems the token in the following action:

[HttpPut("account/verify/{userId}/{token}")]
public async Task<IActionResult> VerityEmailAddress([FromRoute]AccountEmailVerifyModel model) {
}

Is transformed to:

Z%2F3+3Q==

So the + and = are decoded, but the / is not.

like image 538
Miguel Moura Avatar asked Jan 06 '20 20:01

Miguel Moura


1 Answers

The key here is that this is being passed as a route parameter and the specific character that’s not being properly decoded is a /. As you might imagine, there's some potential problems when dealing with a / in route parameters, since they're normally treated as route delimiters.

Background

Ultimately, this is a known limitation with both the ASP.NET MVC Framework and now ASP.NET Core. There are quite a few discussions about this on the ASP.NET GitHub site. On #4599 (from 2016), there's a lengthy debate about whether or not this is the correct behavior. On #4445 (from 2019), a contributor from Microsoft committed to providing an option to allow decoding of these parameters.

Unfortunately, however, this didn't make it into either ASP.NET Core 3.1 or ASP.NET Core 5.0—and while it remains open, it has been demoted from a PRI: 1 - Required issue to a severity-minor issue.

Workaround

Until Microsoft provides a solution to this, there are three options for working around the behavior:

  1. Pass the {token} parameter via the query string instead, where it will be fully decoded.
  2. Add code to your application that explicitly decodes the %2F after binding has occurred.
  3. Create your own IModelBinder to modify the model binding behavior itself.

Update: Contributor @Celluj34 has provided a sample implementation of a custom model binder to solve this on the GitHub issue.

None of these are especially satisfying. But this at least confirms that the behavior you're seeing is known and expected, even if it's arguably incorrect.

like image 136
Jeremy Caney Avatar answered Nov 09 '22 04:11

Jeremy Caney