OData / WebApi

OData Web API: A server library built upon ODataLib and WebApi
https://docs.microsoft.com/odata
Other
857 stars 473 forks source link

Cannot include colons, periods, or dollar signs in URL's with IIS #497

Open sixlettervariables opened 9 years ago

sixlettervariables commented 9 years ago

This has been a particularly vexing issue when dealing with IIS, so I understand if your team has absolutely zero idea how to fix it. In a nutshell: how do you make IIS route OData without failing?

The OData WebApi configuration is the following (redacted as necessary):

        public static void Register(CompositionContainer container, HttpConfiguration config)
        {
            config.MapHttpAttributeRoutes();

            var builder = ConfigureODataModel(container);

            config.MapODataServiceRoute(
                routeName: "ODataRoute",
                routePrefix: "",
                model: builder.GetEdmModel());
        }

With the following example controller:

    [Authorize, ODataRoutePrefix("Xyz")]
    public class XyzController : ODataController
    {
        // assume standard boilerplate to get a database

        [EnableQuery, Authorize(Roles = "OP-GetXyzData")]
        public IQueryable<Xyz> Get()
        {
            return this.db.Set<Xyz>();
        }

        [EnableQuery, Authorize(Roles = "OP-GetXyzData")]
        public IHttpActionResult Get([FromODataUri] int key)
        {
            var result = this.db.Set<Xyz>().SingleOrDefault(x=> x.Id == key);
            if (result == null)
            {
                return NotFound();
            }

            return Ok(SingleResult.Create(result));
        }

        [ODataRoute("Default.Abc(yes={yes})"]
        [EnableQuery, Authorize(Roles = "OP-GetXyzData")]
        public IQueryable<Xyz> GetAbc([FromODataUri] bool yes)
        {
            return this.db.Set<Xyz>().Where(x => x.Yes == yes);
        }
    }

When you query something like, http://localhost/OData/Xyz/$count, you get the number as expected. When you query something like, http://localhost/OData/Xyz/Default.Abc(yes=true)/$count, you get an HTTP 500 error with an HRESULT of 0x800703e9 (stack overflow).

I've tried all manner of witchcraft and tomfoolery to get periods working in a URL (never thought folks would ever use those now did you IIS!), which doesn't appear to work for this either. The Web.config contains the usual incantations to allow IIS+OData to pretend to function:

  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
    <handlers>
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <remove name="OPTIONSVerbHandler" />
      <remove name="TRACEVerbHandler" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*" verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
  </system.webServer>

Due to similar errors, we've already given up on using TimeSpan in a URL (colons man...). Is there a way to make IIS and OData work? Or should we give up and use a self-hosted service?

xuzhg commented 9 years ago

@sixlettervariables

Can it work to make path=/*? See detail in: http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/odata-v4/odata-actions-and-functions

sixlettervariables commented 9 years ago

That does not work if you host multiple applications under /.

dtotzke commented 8 years ago

For the path attribute I have path="*." Note the period after the asterisk.

sixlettervariables commented 8 years ago

That does not work with multiple WebApps under /.

xuzhg commented 8 years ago

Can you try the unqualified function call? See detail at http://odata.github.io/WebApi/#06-01-custom-url-parsing: