I communicate with OData services by using Breeze.js and wanna be able to get and save data.
So there are two endpoints which should be used to get and save resources:
1. https://domain.com/smth/getdata
2. https://domain.com/smth/postdata
I created a manager which purpose is to get data, and send them back to server if needed:
var smthManager = new EntityManager(http://domain.com/smth/getdata);
After changing entities in smthManager I have to save them (by using endpoind 2). Investigating documentation I have found the next statement:
you can re-target a "save" to a custom server endpoint such as an
arbitrarily named action method on a separate
So here is the code to "re-target a save":
var so = new SaveOptions({ resourceName: "postdata" }); // also tried with resourceName: 'http://domain.com/smth/postdata'
myEntityManager.SaveChanges(null, so );
But after all these manipulations what can I see that request was sent to https://domain.com/smth/getdata/$batch
Breeze with a WebApi or WebApi2 service supports multiple server endpoints. Breeze with an OData service does not because the OData spec itself only supports a single $batch save for a service.
See http://www.odata.org/documentation/odata-v2-documentation/batch-processing/
Note that any Breeze WebApi or WebApi2 service is a superset of what can be provided directly from an OData service and is in general just as easy to expose your model from ( as long as you have a .NET server).
Related
I have application built on Ember.js (2.13). I have User model and at this moment I work on avatar upload feature. When I modify model and save it then Ember makes PATCH request to my API during it Ember serializer builds nice json-api object and I like it.
When I need to upload image to server I need to make some PUT request to my API with file data I could use jQuery ajax for this. Server will resize and crop image and save it on disk or push it to S3 bucket. But I do not like this way because this request will be created bypassing Ember's serializer and without references to model. So I need to set uploaded filename to User model and save it then I'll have redundant request to server.
I have an idea to transform file to base64 string in Ember.js app and set this string to User model and save it. In this case I'll have one request to server. Is this good way to upload file?
Please advice best practice of uploading files in Ember.js application.
But I do not like this way because this request will be created
bypassing Ember's serializer and without references to model.
There is nothing you can do about this - ember data does not support files. And in many situations ED is not good enough (for example - nested resource URIs, partial updates). I suggest to not be bothered about it too much - if your can't perform some request using ember data, just use Ember.$.ajax.
So I need to set uploaded filename to User model and save it then I'll
have redundant request to server.
No, you don't. Just configure your backend to return full user model (as you do for other get/post/update requests which use ED), and pass result (if request was successful, of course) to pushPayload method of the store. Store will be updated with actual data without additional requests. Example:
this.get('session').authorize('authorizer:token', (headerName, headerValue) => {
const headers = {};
headers[headerName] = headerValue;
/*Instead of data object, you will create a formData*/
const data = {
/*Some data*/
};
Ember.$.ajax(
{
url: '/path-to-resource/id-of-resource',
headers,
type: "PUT",
data
}
)
.then(
(payload) => {
this.store.pushPayload(payload);
},
(response) => {
this.set('errorMessage', stringifyError(response));
}
)
.always(() => {
this.set('isLoading', false);
});
});
UPD: There is an addon, ember-cli-form-data which claims to add support of file upload to ember data. I didn't try it myself, so can't say if it works and how good.
You can give it try using popular ember addon for this.
ember-plupload and ember-uploader addon
Introduction
I have a SAP HANA Cloud Platform account. I have also deployed a Java application to the account and created a test servlet, which returns dummy data.
On the other side i have a SAP UI5 application which i develop on the WebIDE. I created also two destinations:
Destination "virtualTEST" is connected to a SAP Backend System (HANA Cloud Connector)
Destination "javaTEST" is connected to my Java servlet application
The neo-app.json is well configured and can obtain data from the test servlet (the dummy data) and data from the SAP Backend System (OData Gateway).
The problem
Now i want to pass variables to the SAP Backend System (virtualTEST) destination, which should not be visible in the frontend to avoid javascript manipulation.
My first thought
My first thought was that i create a new servlet which acts as proxy. In the SAPUI5 i call the servlet from javaTEST destination and pass the "hidden variables" like /testServlet?targetUrl=https://webide-xxx.hana.ondemand.com/sap/opu/odata/TEST_SRV/TEST?$filter=Var eq '{{MYVAR}}' and the Java application replaces {{MYVAR}} with my real variable. Then the target will be loaded (this is also a destination url to my SAPUI5 application). This does not work, i do not know why, but i think the proxy can not obtain data from the destination of an application.
Also, i think this is not the best solution. How can this be solved? Any ideas or best practices? Can destinations be used in Java application? :)
It is not really clear to me what you want to achieve. Of cause you can call destinations from Java.
<resource-ref>
<res-ref-name>myBackend</res-ref-name>
<res-type>com.sap.core.connectivity.api.http.HttpDestination</res-type>
</resource-ref>
import javax.naming.Context;
import javax.naming.InitialContext;
import com.sap.core.connectivity.api.http.HttpDestination;
...
// coding to lookup the destination "myBackend"
Context ctx = new InitialContext();
HttpDestination destination = (HttpDestination)
ctx.lookup("java:comp/env/myBackend");
// coding to call service "myService" on the system configured in the given destination
HttpClient createHttpClient = destination.createHttpClient();
HttpGet get = new HttpGet("myService");
HttpResponse resp = createHttpClient.execute(get);
from the official documentation. in the HttpGet you could set Params if you like.
In my opion your Backend should be so save you don't have to worry about Javascript manipulations, especially not for exposed OData services
Regards
Mathias
The Short
I have an existing WCF Data Service that I would like to wire up to use in an AngularJS SPA using Breeze.
Can anyone show a noobie level example of how to do that with out access to the actual database (just the OData Service)?
The Long
I have an existing WCF Data Service that is already in use by a WPF app.
I experimenting with web development and would like to wire up to that service using Breeze. In case it matters, I am using Angular (and am setting up via the HotTowel.Angular nuget package).
I have done a fair amount of Googling and I am stuck.
I can see two ways outlined from my searching:
The First
Make is to make a Breeze controller on the server side of my web app.
The problem I see with that is the metadata. From my limited understanding I need to tell breeze all the meta data of my WCF Data Service. I know how to get the meta from my WCF Data Service (the url + $Metadata), but I don't know how to tell this to Breeze.
The Second
This way is more vague in implementation. I got it from the accepted answer on this question: Breeze.js with WCF Data Service.
Basically the answer here does not seem to work. It relies on something called the entityModel that I cannot seem to find (I have an entityManager, but not an entityModel. And the entityManager does not have the properties that the entityModel is shown to have.
In the end I like the idea of the second method best. That way I can directly connect to my odata service with out needed my web app to have a "in-between" server component. But I would happily take anything that does not need entity framework to connect to my database.
I tried several variations of the second option, but I just can't seem to get it to work. I also tried the Breeze samples. It has one for OData, but it still relies on having Entity Framework hook up to the source database.
To to clearly summarize what I am asking: I am looking for a Breeze example that connects to an existing WCF Data Service.
We regret that you were mislead by that old StackOverflow answer which was way out of date and (therefore) incorrect. There is no longer a type called entityModel.
I updated the answer there and repeat here the same advice.
The recommended way to configure Breeze so that it talks to a standard OData source (such as a WCF OData service) is
breeze.config.initializeAdapterInstance('dataService', 'OData', true);
Here's how you might proceed with defining an EntityManager and querying the service:
// specify the absolute URL to the WCF service address
var serviceName = "http://localhost:9009/ODataService.svc";
var em = new breeze.EntityManager(serviceName);
var query = breeze.EntityQuery.from("Customers")
.where("CompanyName", "startsWith", "B")
.orderBy("City");
em.executeQuery(query).then(function(data) {
// process the data.results here.
});
There is some documentation on this subject here.
A Web API OData service differs from a WCF OData service in several respects. But you may still find value in the Angular Web API OData sample.
Have a doubt in angular resource, In this document http://docs.angularjs.org/api/ngResource/service/$resource
Given :
var User = $resource('/user/:userId', {userId:'#id'});
User.get({userId:123}, function(user) {
user.abc = true;
user.$save(); //Doubt here.
});
Just above this they have given
"When the data is returned from the server then the object is an
instance of the resource type and all of the non-GET methods are
available with $ prefix. This allows you to easily support CRUD
operations (create, read, update, delete) on server-side data."
Now consider for example, i have a PHP script /user which performs some operation like insert a record to Mysql Database.
My assumptions :
.$save(), does it save/update, automatically to Database internally with a update statement?, (i do not think So). Also please clarify, How itsupports CRUD operations from client-side-programming.
or, Does this mean the assignment operation user.abc = true should be saved to object. (NOT required, just assigning a value to a object property is enough).
Then What is this $save() Exactly, doing in a client-side- programming.
These are just conventions that the $resource object follows.
$save or save would do a HTTP POST with the model data, on the resource url.
$delete or delete make a HTTP DELETE request on the resource url.
and developers many times add update which does a HTTP PUT on the resource url.
The server still needs to implementation this and provide basic CRUD operation support.
In standard RESTful service (server) the conventions are like
Url: /users Action:GET
would get all user resources
Url: /users/1 Action:GET
would get the user resource with identifier 1
Url:/users Action:POST
should create a new user resource on server
Url: /users/1 Action:PUT
should update the user details for user with id 1
And the client side $resource is modeled around these convention
I had no issues hooking up breeze to querying the azure mobile services rest endpoints however I was not able to figure out how to perform an update/insert.
Doing something like this works great except for the save part.
var datas = new breeze.DataService({
hasServerMetadata: false,
serviceName: serviceName // my endpoint
});
var manager = new breeze.EntityManager({ dataService: datas });
// manager.enableSaveQueuing(true);
var qu = breeze.EntityQuery.from("notification").where("id", "==", 1);
manager.executeQuery(qu).then(function (data) {
data.results[0].isRead = false;
console.log(manager.hasChanges());
manager.saveChanges();
});
How can we use breezejs with the azure mobile service to either insert or update records.
I can see that you're not getting metadata from the service (you set hasServerMetadata: false) and you aren't defining any metadata on the client. Therefore you have an empty BreezeJS entity model which means that every query returns raw JavaScript objects not Breeze entities.
These raw objects are not in cache, they are not change tracked, they don't have any property change notification or binding support. They are just data.
manager.hasChanges() will always be false and manager.saveChanges() won't do anything ... because you never have any entities.
I haven't tried Breeze with AMS (aka "ZUMO") yet and don't know much about it. I'm sure that it will work with Breeze. But someone has to put in some time to discover how to get metadata from the server, how to insert/update/delete, and how ZUMO data flow over the wire.
My understanding is that ZUMO objects are flat objects that map directly to SQL Azure tables. They have no associations with other entities/tables and that you have to manage foreign keys and related-entity loads by hand. It's really not ready for the rich object models typical of business applications.
For the moment, I suggest you stick with ZUMO's own client component for accessing data.
We'll have a Breeze story in due time.