Search code examples
c#asp.net-web-apiasp.net-web-api-routing

How to send a query string that ends in a period character?


I have a web API project, with the following endpoint:

GET api/search/{searchValue}

Controller code:

[RoutePrefix("api/Search")]
public class SearchController : ApiController
{
    [HttpGet]
    [Route("{searchValue}", Name = "GenericSearch")]
    [ResponseType(typeof(SearchResponse))]
    public async Task<IHttpActionResult> Search(string searchValue) {
        ...
    }
}

This works fine for most search strings. But if the search string ends in a period (.) character, the request breaks with a 404; it seems to be interpreting the period as part of the path rather than as part of the query. This is so, even if the request string is Url encoded, e.g.

api/search/foo%2E

If the period is not the last character of the string, it works:

api/search/foo%2Ebar

will correctly search for "foo.bar".

How can I fix this so that users are allowed to search for strings that end with a period character?

UPDATE: After having this question closed as a duplicate of this question, allow me to clarify why this question is different:

  1. The linked question is trying to use a literal period character in the query string. I'm not even doing that; I'm encoding the . as %2E, and it's still not working.
  2. The query works with the period character in the middle. It's only when it's at the end of the query string that it fails.
  3. I already have <modules runAllManagedModulesForAllRequests="true" /> (as suggested by the accepted answer in my web.config.
  4. I tried suffixing the query with a slash character (i.e. api\search\foo%2E\) as suggested in the highest-voted answer; this made no difference.
  5. I tried all the answers suggested there, and none of them made a difference.

Solution

  • UPDATE:

    I failed to mention that the following was also added to my web config file to allow the period to not cause IIS to break.

    <system.web>
        <httpRuntime targetFramework="4.5" sendCacheControlHeader="true" relaxedUrlToFileSystemMapping="true" />
        <!-- ...other code removed for brevity -->
    </system.web>
    

    Primarily relaxedUrlToFileSystemMapping="true"that indicates whether the URL in an HTTP request is required to be a valid Windows file path.

    HttpRuntimeSection.RelaxedUrlToFileSystemMapping Property

    The RelaxedUrlToFileSystemMapping property determines how the URL in an incoming HTTP request will be validated. If this property is false, the URL is validated by using the same rules that determine whether a Windows file system path is valid.


    ORIGINAL

    Using the catch all parameter in the route template {*searchValue} I was able to get the controller action to match the request with route prefix api/search and return as expected. Even for values ending with a period (.), whether URL encoded or not.

    [RoutePrefix("api/search")]
    public class SearchController : ApiController {
        [HttpGet]
        [Route("{*searchValue}", Name = "GenericSearch")] // Matches GET api/Seach/{anything here}
        [ResponseType(typeof(SearchResponse))]
        public async Task<IHttpActionResult> Search(string searchValue) {
            //...
        }
    }