How can I add context metadata to my entities without using EF?
Asked Answered
J

1

2

I have to implement an architecture where, unfortunately, we are using SharePoint 2013 as, effectively, our principle database. (Not my choice, in case you hadn't picked that up). I have an Asp.Net MVC facade application on the server, handling composition of data from SP and a couple of other data sources, and then a JavaScript SPA as client. An additional wrinkle is that the client needs to be able to work offline, so I need to use IndexedDB to store the data for offline access.

This seems a perfect use-case for breeze.js. My basic architecture is to define a strongly typed model in the MVC facade that will wrap the untyped data I get from SP (in the form object["property"] - using the SP Client Side Object Model). Breeze will handle synchronization between this model and the client, and I will use the export/import functionality to cache data in IndexedDB as required.

So far so good. But... the SOA examples on the breeze site are still under development (and to me, this is fundamentally an SOA architecture, with each SP List a service to be composed). The closest thing I can find is the NoDB sample but this hard-codes metadata on the client. I'd like to establish relationships and validation in the MVC model, and then pass these through to the client, so validation can run off the same declaration in both places.

Is this possible? If so - how? If not does anyone have a workaround or a better idea? I'm already resigned to defining the model in two separate places (the facade and, implicitly, the structure of the SP lists). I would dearly like to avoid implementing it a third time in the client. I'm open to having breeze.js talk directly to the SP REST endpoints, but my understanding from https://mcmap.net/q/1781430/-from-jquery-ajax-to-breeze-js-sharepoint-odata-example is that the implementation is flawed and does not expose the required metadata.

Resolution: Based on the accepted answer below, I came to the following solution:

1) Generate a service reference from the SP ListData.svc endpoint - thus creating an edmx and proxy classes.

2) Extend ContextProvider in my Repository and override BuildJsonMetadata like so:

protected override string BuildJsonMetadata()
{
    XDocument xDoc = XDocument.Load(HttpContext.Current.Server.MapPath("PATH_TO_EDMX"));
    String xString = xDoc.ToString();
    xString = xString.Replace("DATA_SERVICE_NAMESPACE", "APP_NAMESPACE");
    xDoc = XDocument.Parse(xString);
    var jsonText = CsdlToJson(xDoc);
    return jsonText;
}

3) Modify breeze.js very slightly, editing line 12383:

var schema = metadata.schema || metadata["edmx:Edmx"]["edmx:DataServices"].schema;

(I could presumably also have fixed this in the ContextProvider by choosing a descendant rather than the root node for my xDoc)

4) - Optionally use @Christoff's very useful T4TS.tt template script to generate a d.ts from the service proxy classes so I can have type safety on the data that breeze loads.

So far so good with this setup - I can perform basic CRUD with metadata, backed by SP as a data source.

Journey answered 19/3, 2013 at 10:44 Comment(0)
P
3

As of v 1.2.7, We have documented Breeze's metadata schema, and json objects that adhere to this schema that are returned from your webservice will now be honored by Breeze.

--- previous post below

We are in the process of documenting how to expose arbitrary server side metadata over the next week or so, followed soon thereafter by some examples of how to consume an arbitrary web service. There are a few small code changes involved as well.

For the time being, until these docs are complete, the best workaround is to create your metadata on the client and use a jsonResultsAdapter to shape the results of your service call into "entities". The metadata you create on the client will be exactly the same as the metadata that you will eventually be creating on the server and sending down to the client.

Hope this helps.

Prescott answered 19/3, 2013 at 17:21 Comment(2)
Jay - thanks for the response. I can tread water for a week or so until the docs are ready, but just on the off chance: I've got an edmx from a service reference - is there any way I can use that insead of a DbContext?Journey
If you take a look at the source code in EFContextProvider class, there is code in the GetCsdlFromDbContext method that extracts pieces from an edmx to build up the json metadata structure. Hope this helps.Prescott

© 2022 - 2024 — McMap. All rights reserved.