Search code examples
c#-4.0asp.net-web-apiodataasp.net-web-api2simple.odata

mapping shared POCO to oData controllers with plural names


I have an ODataController called LoggerEntriesController that returns a POCO type of WebModels.LoggerEntry. The POCO is in an external library that is shared between the client and sever.

I register the EntitySet like this:

var builder = new ODataConventionModelBuilder();
builder.EntitySet<WebModels.LoggerEntry>("LoggerEntries");
config.MapODataServiceRoute("odata", "api", builder.GetEdmModel());

In my /api metadata I see:

{
  "@odata.context":"http://localhost:3177/api/$metadata","value":[
    {
      "name":"LoggerEntries","kind":"EntitySet","url":"LoggerEntries"
    },{
      "name":"LoggerEntry","kind":"EntitySet","url":"LoggerEntry"
    }
  ]
}

This causes issues with Simple.Odata.Client being unable to resolve LoggerEntry to the /api/LoggerEntries url and I get a 404 when making strongly typed calls like:

await this.Client
    .For<LoggerEntry>()
    .Set(new LoggerEntry()
    {
        Title = title,
        Message = message,
    })
    .InsertEntryAsync();

This leads me to believe that the /api metadata should be like:

{
  "@odata.context":"http://localhost:3177/api/$metadata","value":[
    {
      "name":"LoggerEntry","kind":"EntitySet","url":"LoggerEntries"
    }
  ]
}

I am not sure what I am doing wrong, or what I need to do to get the latter metadata result from the ODataConventionModelBuilder.


Solution

  • I believe the problem is that you have both LoggerEntries and LoggerEntry entity sets in your service metadata, and Simple.OData.Client picks the first it one that satisfies its rules (which are quite simple reflecting the library name - it accepts anything that matches the name either in plural or singular form).

    The version 5 of S.O.D will have more strict control over naming conventions, but even using this version I believe you should be able to get around the problem by specifying explicitly the entity set name, i.e.

    await this.Client
        .For<LoggerEntry>("LoggerEntries")
        .Set(new LoggerEntry()
        {
            Title = title,
            Message = message,
        })
        .InsertEntryAsync();