views:

312

answers:

1

The project we are working on is a classic 3 tiered architecture. tier 1 being the database server, tier 2 the application services and tier 3 the presentation tier (a web site).

In the application services tier I have a project that includes an entity framework model and a WCF data services based service that exposes the entities within the model e.g.:

public class DataService : DataService< PortalEntities >

This is a fully fledged OData service that can be queried through the URI e.g.: /dataservice.svc/mytable?$filter=contains(fieldname,’string’). This is great for the guys developing anything using jQuery as all they have to do is define the query. The problem is that this service is a mid-tier so it cannot be seen by the outside world.

The solution that I am trying is to expose another WCF data service on the web site that exposes the entities created by the service reference. If I add a service reference to the mid-tier service it gives me a data context that data context is being used in the new WCF Data service:

public class DataService : DataService< PortalEntities >

I do have to overwrite the CreateDataSource:

protected override PortalEntities CreateDataSource()
{
    return new PortalEntities(GetMianModelServiceUri());
} 

The new service does act like a proxy and does return the entities exposed (the query .../Services/OData/DataService.svc/tbl_Country works fine).

But when a query is passed to the service e.g.: .../OData/DataService.svc/tbl_Country?$select=Name it throws a not implemented exception.

Any ideas on how to extend the web site service so that it supports the same queries as the mid-tier service?

A: 

Hi,

If you don't need to change the shape or functionality of the data server, you should be able to simply forward the requests and responses, just like a transparent HTTP proxy. The only difference you might need to do is to tweak the service URL. Since the proxy service will have a different base URI than the real service, the payload would contain the real service URIs (in the links and such), which would not work. You can workaround this by using a custom host for your real service and lie to it about its URI. This is done through IDataServiceHost2 interface, you return the "new" URI from the AbsoluteRquestUri and AbsoluteServiceUri properties. Nice sample of an implementation of the interface (although for a different purpose) is here: http://blogs.msdn.com/b/tom_laird-mcconnell/archive/2010/01/18/using-ado-net-wcf-data-services-for-streaming-infinite-event-result-sets.aspx.

If you need to change the shape or functionality, then you really need a true layering.

Layering one WCF Data Service over another is currently rather hard. The LINQ expression trees generated by the "Server" are not always understood by the "Client" LINQ provider. That's what you're running into.

There's a prototype (more like an experiment) of making this work to some extent by rewriting the expression trees. It's part of the OData Provider Toolkit which you can download here http://www.odata.org/developers/odata-sdk#/media/7579/odataprovidertoolkit.zip. (It's in the Experimental folder, AstoriaOverAstoria project).

But please be aware that this is really just an experiment to show what kind of issues are there to be solved and so on. I definitely recommend to NOT use it in any kind of production environment.

Vitek Karas MSFT