title: How to prevent HTTP 404 for a custom action in an odata controller?
body: <p>I have an <code>ASP.Net</code> <code>WebApi2</code> project hosting odata both <code>ApiController</code> and <code>ODataController</code>.  </p>
  
  <p>And I want to add a custom action in an <code>ODataController</code>.  </p>
  
  <p>I saw this seems to be achievable by either adding <code>[HttpPost]</code> attribute on the desired action, or by configuring the <a href="https://msdn.microsoft.com/en-us/library/system.web.odata.builder.ODataConventionModelBuilder%20(v=vs.118).aspx" rel="nofollow noreferrer">ODataConventionModelBuilder</a> with a specific <a href="https://msdn.microsoft.com/en-us/library/system.web.odata.builder.functionconfiguration(v=vs.118).aspx" rel="nofollow noreferrer">FunctionConfiguration</a> when using the <a href="https://msdn.microsoft.com/en-us/library/system.web.odata.extensions.httpconfigurationextensions.mapodataserviceroute(v=vs.118).aspx" rel="nofollow noreferrer">MapODataServiceRoute</a>.  </p>
  
  <p>To distinguish between odata routes and webapi routes we use the following scheme :  </p>
  
  <ul>
  <li>odata  : <a href="http://localhost:9292/myProject/odata" rel="nofollow noreferrer">http://localhost:9292/myProject/odata</a></li>
  <li>webapi : <a href="http://localhost:9292/myProject/api" rel="nofollow noreferrer">http://localhost:9292/myProject/api</a></li>
  </ul>
  
  <p>I tried both these solution without success which all led to get an <strong>HTTP 404</strong> result.  </p>
  
  <p>My custom action is defined as following:  </p>
  
  <pre><code>public class SomeModelsController : ODataController
  {
      //...
  
      [EnableQuery]
      public IHttpActionResult Get()
      {
          //...
          return Ok(data);
      }
  
      public IHttpActionResult MyCustomAction(int parameterA, int parameterB)
      {
          //...
          return Json(data);
      }
  
      //...
  }
  </code></pre>
  
  <p>So as you guessed it, the Get call on the controller perfectly work with odata. However the MyCustomAction is a bit more difficult to setup properly.</p>
  
  <p>Here is what I have tried :</p>
  
  <ol>
  <li><p>Setting an [HttpPost] attribute on MyCustomAction</p>
  
  <pre><code>[HttpPost]
  public IHttpActionResult MyCustomAction(int parameterA, int parameterB)
  {
      //...
      return Json(data);
  }
  </code></pre>
  
  <p>I also tried decorating MyCustomAction with the <code>[EnableQuery]</code> attribute.<br>
  Also, I tried adding the <code>[AcceptVerbs("GET", "POST")]</code> attribute on the method without changes.  </p></li>
  <li><p>Configuring the ODataConventionModelBuilder  </p>
  
  <pre><code>  private static IEdmModel GetEdmModel()
    {
        var builder = new ODataConventionModelBuilder
        {
            Namespace = "MyApp",
            ContainerName = "DefaultContainer"
        };
        // List of entities exposed and their controller name
        // ...
        FunctionConfiguration function = builder.Function("MyCustomAction ").ReturnsFromEntitySet&lt;MyModel&gt;("SomeModels");
        function.Parameter&lt;int&gt;("parameterA");
        function.Parameter&lt;int&gt;("parameterB");
        function.Returns&lt;MyModel&gt;();
  
        return builder.GetEdmModel();
    }
  </code></pre>
  
  <p>Also tried decoration of MyCustomAction with <code>[EnableQuery]</code>, <code>HttpPost</code> and <code>[AcceptVerbs("GET", "POST")]</code> attributes.  </p></li>
  </ol>
  
  <p>I still get <strong>HTTP 404</strong> result.</p>
  
  <p>My query url is as follow:<br>
  <code>http://localhost:9292/myProject/odata/SomeModels/MyCustomAction?parameterA=123&amp;parameterB=123</code></p>
  
  <p>I also tried to POST parameters on
  <code>http://localhost:9292/myProject/odata/SomeModels/MyCustomAction</code> with the same result. Actually with or without parameters I get <strong>HTTP 404</strong> status.</p>