path parameters w/ URL unfriendly characters

2019-05-23 02:45发布

问题:

Using service stack 3.9.21. Hosting the app in IIS 7.5. Using an Integrated 4.0.30319 ASP.NET app pool.

For illustration purposes let's say I have the following path (that is backed by a DTO and a corresponding request handler):

/cars/{id}

Some cars' ids have characters in them that I suppose have to be URL encoded - pipe, |, is one of them. When I send requests to fetch a car with for example an id of '1|2' I get a good old 500 with the following stack trace:

[ArgumentException]: Illegal characters in path.
   at System.IO.Path.CheckInvalidPathChars(String path)
   at System.IO.Path.GetFileName(String path)
   at ServiceStack.MiniProfiler.UI.MiniProfilerHandler.MatchesRequest(IHttpRequest request) in C:\src\ServiceStack\src\ServiceStack\MiniProfiler\UI\MiniProfilerHandler.cs:line 24
   at ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory.GetHandler(HttpContext context, String requestType, String url, String pathTranslated) in C:\src\ServiceStack\src\ServiceStack\WebHost.Endpoints\ServiceStackHttpHandlerFactory.cs:line 153
   at System.Web.HttpApplication.MaterializeHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

I get this regardless of whether I URL encode the pipe in the path or not. How can I solve this problem?

More details

DTO

using ServiceStack.ServiceHost;

namespace SSUEB
{
    [Route("/cars/{id}", "GET")]
    public class ById
    {
        public string Id { get; set; }
    }
}

Endpoint

using System.Collections.Generic;
using System.Net;
using ServiceStack.Common.Web;
using Stack = ServiceStack.ServiceInterface;

namespace SSUEB
{
    public class Cars : Stack.Service
    {
        public object Get(ById byId)
        {
            return new HttpResult(new Dictionary<string, string> {{"id", byId.Id}}, HttpStatusCode.OK);
        }
    }
}

App

using ServiceStack.WebHost.Endpoints;

namespace SSUEB
{
    public class SSUEB : AppHostBase
    {
        public SSUEB() : base("ServiceStack toy service", typeof(SSUEB).Assembly)
        {
        }

        public override void Configure(Funq.Container container)
        {
            ServiceStack.Text.JsConfig.EmitCamelCaseNames = true;
            SetConfig(new EndpointHostConfig { DebugMode = true });
        }
    }
}

Requests

This one:

curl -v -X GET -H "Accept: application/json" http://localhost:80/dealership/cars/123%20456

Gets the expected 200 response:

{"id":"123 456"}

But this one:

curl -v -X GET -H "Accept: application/json" http://localhost:80/dealership/cars/123%7C456

results in the originally reported issue.

IIS Request Log shows that the %7C gets decoded as a pipe and that the %20 gets decoded (in the log at least as a plus). The latter results in a 200 (OK) response, the former - 500 (Internal Server Error).

2012-12-03 22:21:20 127.0.0.1 GET /dealership/cars/123|456 - 80 - 127.0.0.1 curl/7.27.0 500 0 0 5
2012-12-03 22:21:25 127.0.0.1 GET /dealership/cars/123+456 - 80 - 127.0.0.1 curl/7.27.0 200 0 0 1

回答1:

I've had a look at this and there's nothing that we can do in ServiceStack to allow this as it's a pre-validated exception generated by ASP.NET, see Scott Hanselman's post on how to allow invalid chars in IIS/ASP.NET.

Note: As it doesn't go through ASP.NET this is allowed with ServiceStack's self-host as seen from this HttpListener integration test.