59

I have an ApiController and I want to use email addresses as the ID parameter for requests:

// GET api/employees/email@address.com
public CompactEmployee Get(string id) {
   var email = id;
   return GetEmployeeByEmail(email);
}

However, I cannot get this to work (returns 404):

http://localhost:1080/api/employees/employee@company.com

The following all work:

  • http://localhost:1080/api/employees/employee@company
  • http://localhost:1080/api/employees/employee@company.
  • http://localhost:1080/api/employees?id=employee@company.com

I have set relaxedUrlToFileSystemMapping="true" in my web.config as detailed by Phil Haack.

I would very much love the full email address to work, but any time the period is followed by any other character, the request returns a 404. Any help would be greatly appreciated!

Solution

Due to a lack of other options, I've headed in the direction Maggie suggested and used the answer from this question to create a rewrite rule to automatically append a trailing slash when I need an email in the URL.

<system.webServer>
  ....   
  <rewrite>
    <rules>
      <rule name="Add trailing slash" stopProcessing="true">
        <match url="^(api/employees/.*\.[a-z]{2,4})$" />
        <action type="Rewrite" url="{R:1}/" />
      </rule>
    </rules>
  </rewrite>
</system.webServer>
Community
  • 1
  • 1
Jon
  • 4,925
  • 3
  • 28
  • 38
  • 1
    Also see similar question: http://stackoverflow.com/questions/11728846/dots-in-url-causes-404-with-asp-net-mvc-and-iis – Mightymuke Nov 24 '12 at 21:18
  • Thank you @Jonathan-Freeland, this solved my same issue. I'm left shaking my head that Microsoft thought this was a good design. Any other web framework worth its salt would let you quickly and easily configure static / dynamic URLs with a regex or *anything* other than assuming a period always means a static file and causing developers to jump through hoops to work around this assumption. What an unnecessary time waster. – Gojira May 02 '16 at 15:13
  • Thanks @Jonathan-Freeland! I was in a situation where I couldn't change the client but just needed to add the darn slash at the end, your solution worked perfectly for me – Brian Noyes May 05 '16 at 21:12

3 Answers3

84

Would adding a trailing slash work for your scenario?

http://localhost:33021/api/employees/employee@company.com/
Maggie Ying
  • 10,095
  • 2
  • 33
  • 36
  • 1
    It does, but would love to avoid this if possible. – Jon Nov 08 '12 at 23:04
  • Can anybody do a quick write up on why adding the Slash Forces Asp.net to skip the handlers that tries to load Extension Oriented Resources? – Ehsan Samani Jul 30 '15 at 22:31
  • Does fix the issue, but I have get the 404 on one server deploy, and the expected response from another deployment for the same code base. So there is another underlying configuration issue where, if configured correctly, the trailing slash is not required. – mdisibio Jun 12 '17 at 16:57
2

Check your IIS settings:

Home Directory -> Configuration

Edit the .aspx application extension and ensure that the setting Verify that file exists is off.

UPDATE

I've just tested with a default MVC4 Web API project

URL: http://localhost:10983/api/values/cool@email.com

Action in ValuesController:

public string Get(string id)
{
    return id;
}

This was the response:

<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">cool@email.com</string>
Mightymuke
  • 5,094
  • 2
  • 31
  • 42
  • Hi, I'm curious to know if you checked this as it's been an issue for me in the past (honestly - just curious). Thx. – Mightymuke Nov 14 '12 at 22:38
  • 1
    Embarrassingly no. But I have now (and it worked, although TBH I didn't expect it to). Will update my answer. Thx – Mightymuke Nov 16 '12 at 07:50
1

This is what worked for me:

I was running on targetFramework = 4.6.1. I have upgraded to 4.6.2 and added this in web.config:

<system.web>
        <customErrors mode="Off"/>
        <compilation debug="true" targetFramework="4.6.2"/>
        <!-- This will allow to search for stuff that contains . & etc.-->
        <httpRuntime targetFramework="4.6.2" maxRequestLength="100000" maxUrlLength="2048" relaxedUrlToFileSystemMapping="true" requestPathInvalidCharacters=""/>
  </system.web>

The requestPathInvalidCharacters="" is to be able to have stuff like & etc in URI, in encoded form, of course.

Nightrain
  • 391
  • 3
  • 6