ASP.NET Web API OData - Translation of DTO Requests into Entity Requests

We are currently exploring the use of OData query syntax in our web APIs. We are not aiming to implement a full OData implementation - we just use the query syntax.

It is generally considered a good application architecture for dividing your application into several levels. In modern web applications, these layers will include a data layer and a user interface / transport layer, which can model the information stored in your database in different ways when sent to your customers.

for example: you may have an Entity Framework database model that looks like this:

public class Employee { public Guid Id {get; set;} public string Name {get; set;} public int AccessLevel {get; set;} } 

but your web APIs may provide this data to your clients in a different format:

 public class EmployeeDto { public string Name {get; set;} public string SecurityClearence {get; set;} } 

Using the ASP.NET Web API and (presumably?) The Microsoft ASP.NET OData Web API libraries, how could we reach a scenario where our clients would write a query regarding the DTO format, for example:

 ?$filter=(SecurityClearence eq 'TopSecret') 

... and then we will translate this into our data format. eg:

 ?filter=(AccessLevel eq 007) 

or some other format that will allow me to dynamically query my database, such as an expression. eg:

 db.Employees.Where(translatedExpression); 

I thought of several ways to accomplish this manually, but I am interested in understanding how other people will solve this because I feel that my implementation is still pretty crude and is unlikely to lend itself to verification.

Are there any OData Web API library features (and related EDM libraries) that some or all of this could get for me?

+7
c # expression asp.net-web-api asp.net-web-api-odata ado.net-entity-data-model
source share
3 answers

Gavin

I know it might be too late for this party, but here are my two cents on this.

Back in 2013, I was working on a project and came up with the same scenario. I had an entity model as well as a DTO model that had to be ported to and from the service level. I did my research, but did not find any libraries that would allow me to: 1. Automatically convert a map from my entity model to my DTO model and 2. Translate filtering and sorting expressions into DTO entity models.

In the end, I decided to encode my own β€œprediction” framework. A few months ago, I published the GitHub code and downloaded NuGet if someone needed to do something like this.

Now, if you decide to try, you need to create and configure a ProjectionsModel (similar to how you configure the data model of the first EF code) and indicate how the DTO model classes are mapped to the object model model.

 using ExpressionFramework.Projections; namespace TestDTO { public class MyProjectionModel : ProjectionModel { protected override void OnModelCreating(ProjectionModelBuilder modelBuilder) { modelBuilder .Projection<UserAccountDTO>() .ForSource<UserAccountEntity>(configuration => { configuration.Property(dto => dto.RoleCount).ExtractFrom(entity => entity.Roles.Count()); }); } } } 

Then you can create a model and use it to project and filter DTO queries into entity queries:

 IQueryable<UserAccountEntity> usersQuery = usersList.AsQueryable(); var myProjectionModel = new MyProjectionModel(); var dtoUsersList = myProjectionModel.Project<UserAccountDTO, UserAccountEntity>(usersQuery).ToList(); 

Even hard filtering is not part of the example; you can create a collection of QueryFilter and QuerySorter and send them as parameters to the Project method.

Let me know if you want to know more about this library.

+2
source share

We used a combination of Entity Framework, Automapper and LinqToQueryable.

A typical controller action would look like this:

 [HttpGet] [LinqToQueryable] public IEnumerable<SomeViewModel> SomeAction() { return _databaseContext.Entities .Where(e => e.SomeProp = "Example") .Project() .To<SomeViewModel>(); } 

The packages we needed were LinqToQuerystring , linqtoquerystring.entityframework , LinqToQuerystring.WebApi . Docs are here: http://linqtoquerystring.net/

0
source share

Our company also wants to do this. One possible solution that I have been considering is to create a custom IQueryable LINQ Provider. This provider will be able to translate a clean model into a database model and request the appropriate fields, as well as convert the data.

A piece of cake, right? Hmm .. yes ... we haven't started yet.

If anyone has any further suggestions let me know.

Walkthrough: Creating an IQueryable LINQ Provider

LINQ: Creating an IQueryable Provider - Part I

0
source share

All Articles