2

I want to enable camel casing of my odata results. So I added EnableLowerCamelCase. But after I enabled that I get the following error message when I call:

http://localhost/odata/Users

The EDM instance of type '[Core.DomainModel.User Nullable=True]' is missing the property 'id'.

Everything worked before I EnableLowerCamelCase, and it works again if I remove it. Also the error message is rather confusing. It says that User is missing the 'id' property. Which cannot be true. Because I have 'Id' defined as the key.

var builder = new ODataConventionModelBuilder();
builder.EnableLowerCamelCase();

var users = builder.EntitySet<User>(nameof(UsersController).Replace("Controller", string.Empty));
users.EntityType.HasKey(x => x.Id); // <--- id property

builder.GetEdmModel();

What am I doing wrong?

Snæbjørn
  • 10,322
  • 14
  • 65
  • 124
  • It seems to be looking for the property 'id' somewhere in the code whereas it is actually defined as 'Id'. Is this possible ? – Chris Neve Sep 01 '16 at 10:39
  • The POCO class User has Id defined with Pascal Casing as it should be in C#. But the whole point of EnableLowerCamelCase is to convert these PascalCased properties to camelCased so the json result is formatted correctly – Snæbjørn Sep 01 '16 at 10:41
  • I can't repro this, pls give more information like the model – Fan Ouyang Sep 02 '16 at 05:46
  • I have this same issue - Microsoft.AspNet.OData 6.1.0, Versioning 2.2.0, OData.Core 7.5.0 – Travis Sharp Jul 16 '18 at 16:00

1 Answers1

1

The way I solved this was to remove the entity key declaration from the EDM Model and to specifying it in the model itself So my edm looks like `

var builder = new ODataConventionModelBuilder(serviceProvider);
builder.EnableLowerCamelCase();
var subscriptionSet = builder.EntitySet<SubscriptionDTO>("Subscriptions");
  subscriptionSet.EntityType
            .Filter() // Allow for the $filter Command
            .Count() // Allow for the $count Command
            .Expand() // Allow for the $expand Command
            .OrderBy() // Allow for the $orderby Command
            .Page() // Allow for the $top and $skip Commands
            .Select(); // Allow for the $select Command

  // subscriptionSet.EntityType.HasKey(s => s.Id);
  //subscriptionSet.EntityType.EntityType.Property(s => s.Id).IsOptional();`

In the model use DataAnnotations to identify the key:

public class BaseModel
  {
    [Key]
    public Guid? Id {get; set;}
    public Guid? TenantId {get; set;}
    public string Type {get; set;}
    public bool Active {get; set;} = true;

    public BaseModel() {
        this.Id = System.Guid.NewGuid();
    }

then use DTOs with Automapper as per convention:

[JsonObject(NamingStrategyType = typeof(CamelCaseNamingStrategy))]

    public class BaseDTO
    {
        public Guid? Id {get; set;}
        public Guid? TenantId {get; set;}
        public string Type {get; set;}
        public bool Active {get; set;} = true;

        public BaseDTO() {
            this.Id = System.Guid.NewGuid();
        }

    }

 [JsonObject(NamingStrategyType = typeof(CamelCaseNamingStrategy))]
    public class SubscriptionDTO: BaseDTO
    {
        [JsonProperty("email")]
        public string Email {get; set;}

        public SubscriptionDTO(): base() {
           this.Type = "subscription";
        }
    }
Alberto L. Bonfiglio
  • 1,767
  • 23
  • 38