9

I'm using C# .NET WebApi to create an API proxy, here is basic code that I have that works fine for most calls:

[HttpGet]
[Route("api/proxy/{*.}")]
public async Task<HttpResponseMessage> Get()
{
   // some route here...
}

But when I have a URL with special chars, like : (%3F) or / (%2F) it fails with 404. If I remove the special chars, it works.

http://localhost:3000/api/proxy/viewing/v1/items/urn%3Aadsk.viewing%3Afs.file%3AdXJuOmVUE_dmVyc2lvbj0x%2Foutput%2Fd4b6ef1c-8d219bd84c9d%2F0.pf?domain=http%3A%2F%2Flocalhost%3A3000

And tried a few suggestions on web.config, but nothing:

<system.web>
  <httpRuntime targetFramework="4.6" requestPathInvalidCharacters=""/>
  <pages validateRequest="false" />
</system.web>

All other WebApi endpoints are working with a Global.asax like this:

public class Global : System.Web.HttpApplication
{
  protected void Application_Start(object sender, EventArgs e)
  {
    GlobalConfiguration.Configure(Config.WebApiConfig.Register);
  }
}

And the Config.WebApiConfig:

public class WebApiConfig
{
  public static void Register(HttpConfiguration config)
  {
    config.MapHttpAttributeRoutes();
  }
}
Augusto Goncalves
  • 8,493
  • 2
  • 17
  • 44
  • Hasn't this question been asked and answered before? https://stackoverflow.com/a/14368595/495455 and the official source is Scott Hanselmans blog [Experiments in Wackiness: Allowing percents, angle-brackets, and other naughty things in the ASP.NET/IIS Request URL](http://www.hanselman.com/blog/ExperimentsInWackinessAllowingPercentsAnglebracketsAndOtherNaughtyThingsInTheASPNETIISRequestURL.aspx) – Jeremy Thompson Jun 20 '17 at 04:10
  • you could try the quick and dirty route: System.Uri.EscapeDataString(string data).....to return a string without those special characters? (also curious is this for a forge related project?) – BenKoshy Jun 20 '17 at 07:39

2 Answers2

5

According to the answer MVC WEB API routing fails when url contains encoded ampersand you need to remove characters that you consider valid from requestPathInvalidCharacters property of httpruntime:

<httpruntime requestvalidationmode="2.0">
             requestPathInvalidCharacters="*,:,&amp;,\"
             relaxedUrlToFileSystemMapping="true" />

But it is much more safe to pass those parameters as query string.

EDIT:

I have tested url form your question http://localhost:3000/proxy/target/v1/urn%3Aparam%2Foutpu?domain=http%3A%2F%2Flocalhost%3A3000 and it works by simply allowing % character. So you need to list allowed characters there in the requestPathInvalidCharacters property, i.g: %,&amp;,*,\. My current config is:

<httpRuntime targetFramework="4.6.1" requestPathInvalidCharacters="%" />

EDIT 2:

I have made some more research and found an answer to ASP.net MVC4 WebApi route with file-name in it. Simple solution is to add runAllManagedModulesForAllRequests property to modules section in web config. If you check accepted answer you can try to fine-tune the solution to reduce the impact of running all managed modules.

To conclude, you need to modify following sections. I have removed only : from default value of requestPathInvalidCharacters, which applies to already decoded URL and has nothing to with % characters in encoded URL:

<system.web>
  <httpRuntime requestPathInvalidCharacters="&lt;,&gt;,*,%,&amp;,\,?"/>
</system.web>

<system.webServer>
  <modules runAllManagedModulesForAllRequests="true">
  ...
  </modules>
</system.webServer>
Andrii Litvinov
  • 12,402
  • 3
  • 52
  • 59
  • I tried that, but the invalid chars is not accepting on the file, VS complains with invalid chars – Augusto Goncalves Jun 14 '17 at 16:28
  • @AugustoGoncalves, I have updated my answer, it works by simply adding `%` to `requestPathInvalidCharacters` property. – Andrii Litvinov Jun 14 '17 at 16:44
  • this works for %, but still failing on . (dot). If I add it to requestPathInvalidCharacters, the whole app throw "A potentially dangerous Request.Path value was detected from the client (.)." (and thanks for your help so far) – Augusto Goncalves Jun 14 '17 at 17:17
  • as this is a proxy, I cannot change the incoming URL, so my app needs to support % . = _ ? and a few others – Augusto Goncalves Jun 14 '17 at 17:18
  • @AugustoGoncalves all those are legal characters, with same config URL `/proxy/t.ar=ge_t/v1/urn%3Aparam` works fine. The only problem with `.` is that of it appears in last section IIS will consider it is file name and extension separator and will return 404. Could you maybe provide a list of URLs that you need to support to see if it's possible at all? How make a call to that URL? Won't it be possible to change it to `/proxy?url=viewing/v1/items/urn%3Aadsk.viewing%3Afs.file%3AdXJuOmVUE_dmVyc2lvbj0x%2Foutput%2Fd4b6ef1c-8d219bd84c9d%2F0.pf?domain=http%3A%2F%2Flocalhost%3A3000` from you example? – Andrii Litvinov Jun 14 '17 at 18:04
  • I updated my question with the real URL, and I cannot change it... :-( – Augusto Goncalves Jun 14 '17 at 18:09
  • @AugustoGoncalves, it fails with 404 because IIS thinks it is local file and don't even invoke web api routing. Probably should be possible to configure IIS not to serve static files or something. Is it an option for you? – Andrii Litvinov Jun 14 '17 at 18:11
  • @AugustoGoncalves, Another option is to setup Application Request Routing on your IIS server and modify the URL so that it can be processed by web api. Will that be an option? – Andrii Litvinov Jun 14 '17 at 18:15
  • don't have control over IIS on PROD, probably cannot make those changes – Augusto Goncalves Jun 14 '17 at 18:17
  • @AugustoGoncalves, I have updated the answer with the solution that will work for you. – Andrii Litvinov Jun 15 '17 at 07:46
  • @AugustoGoncalves, great, I am glad you helped! – Andrii Litvinov Jun 20 '17 at 12:29
  • if you can give another tip at https://stackoverflow.com/questions/44682818/httpclient-on-webapi-is-extremely-slow – Augusto Goncalves Jun 21 '17 at 17:56
1

Try this 2 changes in web.config.

<system.web>
   <httpRuntime targetFramework="4.6" requestPathInvalidCharacters=""/>
</system.web>
...
<system.webServer>
<handlers>
  ...
  <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*" verb="*" type="System.Web.Handlers.TransferRequestHandler"
    preCondition="integratedMode,runtimeVersionv4.0"/>
</handlers>

Note: I set an empty list in requestPathInvalidCharacters and change the path filter in the handler to "*".

Gerardo Seró
  • 33
  • 1
  • 5