Search code examples
c#.netasp.net-core-webapi.net-6.0

Endpoint removing hash and everything after in string parameter


I have a .NET 6.0 API project using Web API but having some trouble with getting a string value to pass through properly.

The endpoint is:

[HttpGet("contact/{userId}")]
public async Task<ActionResult<string>> GetUserAsync(string userId)
{
    var user = await _userService.GetUserAsync(userId);

    return user is null ? NotFound() : Ok(user);
}

When I pass in a userId with a # it strips off the hash and everything after. For example, if I pass in example-id-#1 the endpoint recieves example-id-.

If I pass in a string without a # the whole string comes through.

So my questions are:

  1. Why does Web API strip the value?
  2. How would I fix this without changing the value passed in?

Thanks!


Solution

  • # is reserved symbol in Uniform Resource Identifier (URI) schema, which defines fragment of URI:

    enter image description here

    Fragment: An optional fragment component preceded by a hash (#). The fragment contains a fragment identifier providing direction to a secondary resource, such as a section heading in an article identified by the remainder of the URI. When the primary resource is an HTML document, the fragment is often an id attribute of a specific element, and web browsers will scroll this element into view. https://en.wikipedia.org/wiki/Uniform_Resource_Identifier

    So in your example if URI is http://localhost:3000/contact/example-id-#1. It means following:

    • Schema - http
    • Host - localhost
    • Port - 3000
    • Path - /contact/example-id- with two segments, contact and example-id-
    • Fragment - 1

    Attribute [HttpGet("contact/{userId}")] roughly means for asp.net binder: "in the Path, take the next Segment after Segment contact and pass it as input parameter named userId". As you can see from the definition of URI, it correctly takes value example-id-.

    If client wants to pass something, which includes reserved URI character, it should pass it URL encoded way, which basically means reserved characters will be substituted with codes to not mess with URI schema. So the URI will look like http://localhost:3000/contact/example-id-%231.

    How would I fix this without changing the value passed in?

    It would be not so easy. You can get URI, which were used to hit the action, with UriHelper.GetDisplayUrl(HttpRequest) as a string, and then parse it manually to extract the needed part. But please don't do it. It breaks URI scheme expectations, and could bring problems in routing.