0
votes

I am new to OData and EDM. I'm trying to implement them in a solution in Visual Studio 2019 having a Blazor WebAssembly project and a .NET Core 3.1 web API. The problem I'm experiencing is in the web API project.

To configure OData with EDM I'm calling:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
//etc.
app.UseEndpoints(endpoints =>
            {
//etc.
                endpoints.Select().Filter().OrderBy().Count().MaxTop(1000);
                endpoints.MapODataRoute("api", "api", GetEdmModel());
// etc.
            });
        }
}

The GetEdmModel() function is:

private IEdmModel GetEdmModel()
        {
            var odataBuilder = new ODataConventionModelBuilder();
            odataBuilder.EntitySet<ViewStudentDto>("Students");

            return odataBuilder.GetEdmModel();
        }

At runtime I get the error:

System.InvalidOperationException: The entity set Students is based on type > MySchool.Dtos.Students.ViewStudentDto that has no keys defined

I understand the error. It's complaining that my DTO class ViewStudentDto hasn't defined a unique identifier property. But it has. And it's public and the property is named Id according to convention. The problem is that the type of the property is not one of the Edm primitive types from OData spec:

  • Edm.Boolean
  • Edm.Byte
  • Edm.Date
  • Edm.DateTimeOffset
  • Edm.Decimal
  • Edm.Duration
  • Edm.Guid
  • Edm.Int16
  • Edm.Int32
  • Edm.Int64
  • Edm.SByte
  • Edm.String
  • Edm.TimeOfDay

My Id property is a strongly-typed Id (a value object) called StudentId whose underlying type is System.Guid, which maps to Edm.Guid.

It's possible to use strongly typed Ids with Entity Framework Core and Json Serialization by using TypeConverters, JsonConverters and EF configuration. Surely it must be possible to use strongly typed Ids with EDM/OData using some kind of type conversion?

Can anybody please guide me how configure EDM/OData to recognize that my StudentId value object can be unpacked to a simple Edm.Guid so that it doesn't throw this exception?

If the above is not enough to see the problem I'm having, there is a minimal repro of it available here:

https://github.com/BenjaminCharlton/ODataWithStronglyTypedIdsRepro

Thanks for your advice!

Benjamin

1
Can you post your ViewStudentDto and StudentId classes ?agua from mars
Thanks for your continued support! I didn't provide that in the original post because I didn't want to dump a load of unnecessary code on you. But yes, sure! If it will help you to help me I'll happily share it. I have made this Git repository with the minimal amount of code required to show the problem. It's at: github.com/BenjaminCharlton/ODataWithStronglyTypedIdsReprobenjamin

1 Answers

0
votes

Use the builder to specify the key :

private IEdmModel GetEdmModel()
{
    var odataBuilder = new ODataConventionModelBuilder();
    var entitySet = odataBuilder.EntitySet<ViewStudentDto>("Students");

    entitySet.EntityType.HasKey(e => e.Id);
    entitySet.EntityType.Ignore(e => e.StudentId);

    return odataBuilder.GetEdmModel();
}

And add update the DTO to use the Id property:

public class ViewStudentDto
{
    public Guid Id { get => StudentId.Value; set => StudentId = new StudentId(value); }

    [JsonIgnore]
    public StudentId StudentId { get; set; }

    public DateTime WhenEnrolled { get; set; }

    public string Name { get; set; }
}