Snæbjørn
Snæbjørn

Reputation: 10792

OData complains about missing id property when enabling camelcasing

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?

Upvotes: 1

Views: 1666

Answers (1)

Alberto L. Bonfiglio
Alberto L. Bonfiglio

Reputation: 1835

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";
        }
    }

Upvotes: 1

Related Questions