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://stackoverflow.com/a/15364503/1014822 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.
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.
Related
Is it possible to call a stored procedure within javascript on the client side?
I know how to do on the server side, but I am interesting in doing on the client side.
Basically it boils down to directly contacting a SQL server from within the client. Is that possible?
tldr; No, it is not possible to connect to SQL Server 'directly' from browser-JavaScript1.
JavaScript can "speak" HTTP and WebSockets, but SQL Server "speaks" TDS. To communicate there needs to be a common medium/protocol that both the client and server use.
While there are WebSocket proxies that technically make this possible it still requires a separate proxy service (and you'd still have to write/find a JavaScript TDS driver). I don't recommend eliminating the controlled access layer.
Likewise, an HTTP proxy where raw SQL commands are sent to/from the client could be used. I wouldn't advise this either, but some do exist.
External code/libraries (eg. ActiveX, Java) could establish the SQL connection and proxy through to the JavaScript client.
In all of these cases there is an intermediate helper and browser-JavaScript never connects 'directly'.
1 JavaScript is a language and this answer focuses on a browser implementation with browser-supported libraries/functions. One could argue that using node modules would still 'be JavaScript', and they would be correct .. in a different environment.
You cannot establish a direct connection to a database from a client's web browser. What you will need to do is create a server side application to expose an API for getting the data over HTTP.
Take a look at Microsoft's ASP.NET Web API
Sort of
You could create an endpoint that is a wrapper for stored procedure(s) that takes the procedure name as a parameter, as well as the parameters for the procedure.
Once you have such a mechanism in place, you can create endpoints that expose procedures automagically.
http://yourserver/services/yourprocname?prm1=val,prm2=val,etc
If you feel really ambitious you can try out SQL 2016 and return JSON directly from those procedures. Then you can nest data using subqueries and return the JSON in a single payload. No serialization, no objects, just read the data and return it.
< 2016 you could put the results into a Dictionary and use NewtonSoft to serialize it. Assuming you are returning flat data you'd be good to go. Just use a reader and get the meta data from the column names for the key, and the value as object. NewtonSoft will convert that into JSON for you.
If you are returning hierarchical you could (by convention) create a series of runners that take the reader, and pump it into a Dictionary where object is another Dictionary Again the Newtonsoft stuff will help you out with the serialization.
Hope this helps, we are using this approach with 2016 and it is very nice to be able to create a stored procedure and call it without any middle tier code, deployment, etc. It just works.
Hope this helps.
Yes, you can connect to SQL Server from Client side directly by using the WebAssembly. You can write your function that calls the SQL Server in C or C++ first. Compile it to .Wasm by Emscripten compiler. Then you can call the C or C++ code by using JavaScript. In future, you should be able to do that with C# but Microsoft just started work on that.
I am writing a post about it, and I will share it when it's ready.
Now just because you can do it, doesn't mean you should because of security issues. But I am not here to give a lecture about what you should or should not do.
I have my server in nodejs and client in angularjs, mongodb(mongoose) as database. I want my client to be able to make a search query with all the normal consitions put in like fixing few fields to certain values, search string contained in few of the fields etc
query can be
(value of field A can be 'x' or 'y') and
(value of field B can range between dates P and Q) and
(string s contained in fields C or D or E) few more
is there any npm plugin or standardisation I can follow to enrich my server side API and also directly put the expression while querying with out doing a map reduce with multiple queries(with lots of code).
Yes, there are a few. I only know of those that work with Mongoose so if you're using another driver you may need to modify them a bit.
With each of these you'll need to determine which to filter locally and which to let the server handle it. Where you filter should depend largely on how much data you have. Personally, it made more sense to abandon local filtering for my largest sets and simply rely on MongoDB to handle the workload.
angoose
Connecting Mongoose and Angular and More
The original motive for Angoose project is to do away with the dual
model declarations(server and client side) if we are building a rich
model based SPA application using modern Javascript framework such as
Angular and node.js. With both front end and backend using Javascript,
Angoose allows the server side models and services to be used in the
client side as if they reside in the client side.
Angoose depends on following frameworks and assumes you have basic
familarities with them:
mongoose
express
angular (optional, for non-angular app, jQuery is required)
Mongoose Api Query
Mongoose plugin that takes a set of URL params and constructs a query for use in a search API. Also, worst project name ever.
If you use Mongoose to help serve results for API calls, you might be
used to handling calls like:
/monsters?color=purple&eats_humans=true
mongoose-api-query handles
some of that busywork for you. Pass in a vanilla object (e.g.
req.query) and query conditions will be cast to their appropriate
types according to your Mongoose schema. For example, if you have a
boolean defined in your schema, we'll convert the eats_humans=true to
a boolean for searching.
It also adds a ton of additional search operators, like less than,
greater than, not equal, near (for geosearch), in, and all. You can
find a full list below.
When searching strings, by default it does a partial, case-insensitive
match. (Which is not the default in MongoDB.)
Angular Bridge
Link models easily via a REST interface between Mongoose/Node-Express/Angular.js
Create, read, update, delete MongoDB collections via AngularJS.
It uses :
Mongoose for accessing to Mongodb
Express for the routing
AngularJS (with the $resource method)
is there any "ready to you" solution how to export mongoose models to client side app? If I imagine perfect world, mongoose models would let me define which properties and methods of entity is needed on client side and generates needed classes for client so I can easily use them with BreezeJS for example.
Any idea? Or is it road to hell combine it together? :))
Update - As of v 1.2.7 - we have provided two facilities that will help accomplish tasks like this.
The Breeze metadata format has been documented and any json object that adheres to this format and is returned from the breeze metadata call will be used to configure breeze's client side metadata.
The JsonResultsAdapter may be used to reshape or assist with interpreting the result of any web service call so that any results returned by the call can become Breeze entities.
--- Previous post
Please stay tuned, we will be releasing a new version of breeze in the next few days with support for pluggable json adapters that will allow the consumption of any web service. And since breeze metadata can already be defined for an arbitrary model, you should be able to consume your mongoose models pretty easily. Of course, the devil IS in the details.
I'd like to be able to have Javascript code manipulate a persistent JSON object in the browser, and have it synchronise with the server, and other clients in real time.
I'm already using MVC separation.
I'd like to be able to do something like this:
function sendMessageToUser(username, message){
messageID = window.model.userMessages[username].messages.length;
window.model.userMessages[username].messages[messageID] = message;
window.requestModelSync();
}
in this example, window.model is a JSON object that is syncronised periodically or on demand, with errors upon collisions, so 'heavy' client code can handle such an event (it is not caught in the example, but if another user messaged the same user at the same time before syncs occurred, an error might be raised by the sync library).
The view code would be called upon a model change and would re-render the messages for the user - in real time.
Are there any libraries that do this already that are somewhat simple, and open-source?
Assuming it's not so secure, I'd like to add cookie based user authentication and key / value validation to it, assuming it doesn't exist already - while still using JSON, with no schema's or models required to start hacking.
I've seen Robert Sayre's sync.js which could be a key building block but I'd like to see something more fully formed, and preferably in use already. I.E: COMET, collision avoidance / resolution strategies, low bandwidth use etc already implemented.
If it doesn't exist I'd be happy to work on such a plugin with people skilled in Python and Javascript.
I've seen http://persistencejs.org/plugin/sync - it is not JSON, they end up defining their own model class.
I don't want to use something as complex as Apache Wave's API's either. Simplicity for prototyping is a key goal.
Firebase is a good candidate for solving your problem.
There isn't a native Python library, but there is a Python wrapper around the REST API
See:Firebase
Firebase home page
I am playing around with CouchDB to test if it is "possible" [1] to store scientific data (simulated and experimental raw data + metadata). A big pro is the schema-less approach of CouchDB: we have to be very flexible with the metadata, as the set of parameters changes very often.
Up to now I have some code to feed raw data, plots (both as attachments), and hierarchical metadata (as JSON) into CouchDB documents, and have written some prototype Javascript for filtering and showing. But the filtering is done on the client side (a.k.a. browser): The map function simply returns everything.
How could I change the (or push a second) map function of a specific _design-document with simple browser-JS?
I do not think that a temporary view would yield any performance gain...
Thanks for your time and answers.
[1]: of course it is possible, but is it also useful? feasible? reasonable?
[added]
Ah, the jquery.couch.js (version 0.9.0) provides a saveDoc() function, which could update the _design document with the new map function.
But I also tried out the query function, which uses a temporary view. Okay, "do not use this in the real product, only during development"... But scientific research is steady development, right?
Temporary views are getting cached, as I noticed, and it works well for ~1000 documents per DB. A second plus: all users (think of 1 to 3, so a big user management is quit of an overkill) can work with their own temporary view.
Never ever use temporary views. They are really only there for dev and debugging purposes. For more information, see http://wiki.apache.org/couchdb/Introduction_to_CouchDB_views (specifically the bold "NOTE").
And yes, because design documents are really just documents with special powers, you can run you GET/POST/PUT/DELETE methods on them. However, you will usually need admin privileges to do this. So, if you are allowing a client side piece of software to do that, you are making your entire database public for read/write access - this may be fine for your application, but is important to remember.
Ex., if you restrict access to your database, but put the username and password in client side javascript, then anyone can see that username and password.
Cheers.
I´ve written an helper functions for jquery.couch and design docs, take a look at:
https://github.com/grischaandreew/jquery.couch.js