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.
edmx
from a service reference - is there any way I can use that insead of a DbContext? – Journey