OData v4 Function always returns 404
Asked Answered
C

4

6

Trying to move from OData v3 to OData v4. Why do I keep getting a 404 when trying to use OData Functions?

Web API Config:

ODataModelBuilder builder = new ODataConventionModelBuilder();
//etc
builder.EntitySet<LocalizableString>("LocalizableStringApi");
//etc
var getComparitiveTableFunction = builder.EntityType<LocalizableString>().Collection.Function("GetComparitiveTable");
getComparitiveTableFunction.Parameter<string>("cultureCode");
getComparitiveTableFunction.ReturnsCollection<ComparitiveLocalizableString>();
//etc
config.MapODataServiceRoute("OData_Kore_CMS", "odata/kore/cms", builder.GetEdmModel());

C# Code:

[EnableQuery(AllowedQueryOptions = AllowedQueryOptions.All)]
[HttpGet]
//[ODataRoute("Default.GetComparitiveTable(cultureCode={cultureCode})")] // Tried this, but gets errors and I noticed the function is in the OData model anyway without this, so should be fine.
public virtual IHttpActionResult GetComparitiveTable([FromODataUri] string cultureCode)
{
    // Implementation
    return Ok(query);
}

XML Returned from $metadata:

<Schema Namespace="Default">
    <Function Name="GetComparitiveTable" IsBound="true">
        <Parameter Name="bindingParameter" Type="Collection(Kore.Localization.Domain.LocalizableString)"/>
        <Parameter Name="cultureCode" Type="Edm.String" Unicode="false"/>
        <ReturnType Type="Collection(Kore.Localization.Models.ComparitiveLocalizableString)"/>
    </Function>
    ...

As you can see, it's in the schema / OData model... yet the following query does not work:

http://localhost:30863/odata/kore/cms/LocalizableStringApi/Default.GetComparitiveTable(cultureCode='en-US')

I have also tried the following:

http://localhost:30863/odata/kore/cms/LocalizableStringApi/GetComparitiveTable(cultureCode='en-US')
http://localhost:30863/odata/kore/cms/Default.GetComparitiveTable(cultureCode='en-US')
http://localhost:30863/odata/kore/cms/GetComparitiveTable(cultureCode='en-US')

All of the above result in a 404.

So... what am I doing wrong here?

Cogan answered 18/8, 2015 at 3:48 Comment(9)
Whoever downvoted, I would appreciate it if you would say why...Cogan
2 downvotes? Seriously guys.. if you have a problem with my post, have the decency to tell me what it is so I can correct it..Cogan
I don't know who downvote :S .. what's your controller name ?Javed
Hi @FanOuyang. My controller name is LocalizableStringApiController.Cogan
@FanOuyang: In OData V3 I was using the code as an OData action and it was mostly fine but I had some problem that you showed me cannot be fixed with V3 (see: #31823255), so now I am trying to make it an OData function with V4...Cogan
I can't found what's wrong in your code, maybe you can share your project, FYI: odata.github.io/WebApi/#04-06-function-parameter-supportJaved
@FanOuyang, thanks for being so helpful. Please check your inbox.. ;-)Cogan
Two questions related to my own function(s) not appearing when I moved from v3 to v4: Are you using System.Web.OData, or System.Web.Http.OData? The scaffolding will apply System.Web.Http.OData, but for v4 it should omit the Http Do you have more than one custom function? It has been nearly a year since I had trouble with multiple functions where only one function worked. I had to implement this answer https://mcmap.net/q/1630838/-adding-a-new-odata-controller-fails-existing-controller to allow multiple controllers with multiple functions.Margarite
Possible duplicate of Web API 2: OData 4: Actions returning 404Swingle
C
7

I solved this by adding the following line in my web.config, under <system.webServer>:

<modules runAllManagedModulesForAllRequests="true">

This may cause performance issues though, if I remember correctly. So it's not ideal. Any better solutions are very welcome...

Cogan answered 18/8, 2015 at 6:32 Comment(1)
That's true, it's a performance issue (and a potential source of unexpected errors). Please see my answer for an alternative solution.Kerril
S
13

I solve a similar problem adding a trailing slash to the requested url.

Separates answered 8/9, 2015 at 3:24 Comment(1)
Oh wow that worked. Very annoying. Nothing about a trailing slash in the docs! learn.microsoft.com/en-us/aspnet/web-api/overview/…Haunted
C
7

I solved this by adding the following line in my web.config, under <system.webServer>:

<modules runAllManagedModulesForAllRequests="true">

This may cause performance issues though, if I remember correctly. So it's not ideal. Any better solutions are very welcome...

Cogan answered 18/8, 2015 at 6:32 Comment(1)
That's true, it's a performance issue (and a potential source of unexpected errors). Please see my answer for an alternative solution.Kerril
K
3

You need a module that goes by the name of UrlRoutingModule-4.0 to be running through IIS. This solution causes all your registered HTTP modules to run on every request, not just managed requests (e.g. .aspx). This means modules will run on ever .jpg .gif .css .html .pdf etc.

So, a better solution would be to add the following in your web.config

<modules>
  <remove name="UrlRoutingModule-4.0" />
  <add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="" />
</modules>

Source: http://www.britishdeveloper.co.uk/2010/06/dont-use-modules-runallmanagedmodulesfo.html

Kerril answered 2/6, 2016 at 9:9 Comment(0)
S
2

This is a solution to prevent 404 Not Found error with OData functions / actions.

Benefits of this solution

Add theses lines in your web.config

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

Et Voilà :)

Swingle answered 11/9, 2016 at 16:32 Comment(1)
This didn't work for me, but changing the placement of the forward slash worked: <add name="ExtensionlessUrlHandler-Integrated-4.0Custom" path="odata/*" verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />Etiology

© 2022 - 2024 — McMap. All rights reserved.