0
votes

Ive been struggling with this all day and i think ive reached the end of all the answers ive seen on this. Maybe im special, or maybe im doing something stupid. I recently upgraded from V3 to V4 (i think). Im using the System.Web.OData namespace which should be fine.

Here is my WebAPIConfig

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using System.Web.OData.Builder;
using System.Web.OData.Extensions;
using System.Web.OData.Routing;
using System.Web.OData.Routing.Conventions;

using GizmoAPI.Models;
namespace GizmoAPI
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

            ODataModelBuilder builder = new ODataConventionModelBuilder();
            builder.EntitySet<Counterparty>("Counterparties");

            config.Select().Expand().Filter().OrderBy().MaxTop(null).Count();
            config.EnableDependencyInjection();
            config.MapHttpAttributeRoutes();

            config.MapODataServiceRoute("odata", "odata",     builder.GetEdmModel());
            config.AddODataQueryFilter();
            var cors = new     System.Web.Http.Cors.EnableCorsAttribute("http://localhost:56248", "*", "*");
            config.EnableCors( cors);
         config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new             System.Net.Http.Headers.MediaTypeHeaderValue("text/html"));
            config.EnableSystemDiagnosticsTracing();
        }
    }
}

and here is a basic controller:

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.ModelBinding;
using System.Web.OData;
using System.Web.OData.Routing;
using GizmoAPI.Models;

namespace GizmoAPI.Controllers
{
public class CounterpartiesController : ODataController
{
    private GizmoEntities db = new GizmoEntities();

    // GET odata/Counterparties
    [EnableQuery]
    public IQueryable<Counterparty> GetCounterparties()
    {
        return db.Counterparties;
    }

    // GET odata/Counterparties(5)
    [EnableQuery]
    [ODataRoute("{key}")]
    public SingleResult<Counterparty> GetCounterparty([FromODataUri] int key)
    {
        return SingleResult.Create(db.Counterparties.Where(counterparty => counterparty.CounterpartyID == key));
    }

Then im trying to call the URL as http://localhost:60965/odata/Counterparties/101 or http://localhost:60965/odata/101

or really anything at this point. I feel like there is some sort of configuration that im missing to activate it. I get the error "The path template '{key}' on the action 'GetCounterparty' in controller 'Counterparties' is not a valid OData path template. Resource not found for the segment '{key}'."

2

2 Answers

0
votes

Did you try renaming your method to GetCounterParties([FromODataUri] int key) and removing the OdataRoute Attribute?

0
votes

This is not a 100% fix to my problem since i added odata as a tag.

Comparing the ODataController with the ApiController (WebAPI2.2), i couldnt find any reason not to switch to the latter. So i changed my controller to inherit APIController, and switched all references of odata to the WebAPI version. In fact, the code above is almost identical with the exception of the aforementioned controller and the ODataRoute now becoming simply "Route". The code compiles completely fine and is far more manageable. I can even use the odata filters if the return type of my action is iqueryable.