8
votes

I have an ODataController in an Asp.Net Web Api application that allows OData queries. I'm only allowing reads, not updates. Instead of exposing the data model directly, I've created a set of DTOs. The property names on the DTOs do not necessarily match the properties on the EF model. This causes a problem when I try to use the OData query against the EF model. I've looked at other posts on StackOverflow around this subject but none of them seemed to resolve this issue.

Here is what I have right now:

public IQueryable<Customer> GetCustomer(ODataQueryOptions<Customer> query)
{
        ODataModelBuilder builder = new ODataConventionModelBuilder();
        builder.EntitySet<Customer>("Customers");
        builder.EntitySet<RECORD>("Records");
        builder.Namespace = "MyDataService.Models";

        var opts = new ODataQueryOptions<RECORD>(new ODataQueryContext(builder.GetEdmModel(), typeof(RECORD)), this.ActionContext.Request);
        var records = (IQueryable<RECORD>)opts.ApplyTo(db.RECORDS);
        return ConvertToCustomerList(records);
}

This works until I reference specific fields in a select or filter. As soon as I reference a field in my OData query I get an ODataException like - Could not find a property named 'LastName' on type 'MyDataService.Models.RECORD. This is because the EF properties have a different naming convention. In this case it should be using "LAST_NAME".

It seems like I need to parse the query and then replace the field references with the correct names. I found the ODataUriParser which seems like it could help with this but it's not as clean as I was hoping.

Can anyone provide me some pointers in resolving this issue? Is there a better approach?

1

1 Answers

7
votes

The WebApi OData new feature Model Aliasing may resolve your problem. You don't have to have the same names between a Edm Model and a aDTO. for example, there is a property name OrderDto.Total, but in Edm Model it becomes Order.Check

        ODataModelBuilder builder = new ODataConventionModelBuilder();
        builder.ModelAliasingEnabled = true;

        EntitySetConfiguration<CustomerDto> customers = builder.EntitySet<CustomerDto>("Customers");
        EntitySetConfiguration<OrderDto> orders = builder.EntitySet<OrderDto>("Orders");
        orders.EntityType.Name = "Order";
        orders.EntityType.Property(p => p.Total).Name = "Check";
        return builder.GetEdmModel();

Please reference the ODataModelAliasingSample in https://aspnet.codeplex.com/SourceControl/latest#Samples/WebApi/OData/v4/