Write request with Atom/XML

Apr 18, 2012 at 12:09 PM

Hi,

does datajs support change/write requests also when handing over the payload as XML data or do I have to hand the data over in JSON format.

Or anyway how can I achieve that datajs sends the POST/PUT/DELETE requests with the data as XML/ATOM and not with JSON data?

Is this possible?

Thanks.

Apr 18, 2012 at 7:55 PM

Hi Joe,

   Hope you are doing great.  Yes, you can write ATOM/XML using datajs.. by default we favor json... but there are a few ways to change it atom or xml.. 

   1.  In your headers collection, set the content type header to  application/atom+xml

   2.  Use explicitly the atom (or xml handler) by passing OData.atomHandler to the OData.request() function

   3.  Set the the atom handler as the default handler for all requests. You can do this by:

// saving the default handler object is not necessary, 
// but I strongly recommend it in case you need to restore it later.

var oldDefaultHandler = OData.defaultHandler;
OData.defaultHandler = OData.atomHandler;

 Regards,

Alex Trigo.

Apr 19, 2012 at 4:27 PM
Edited Apr 19, 2012 at 4:36 PM

Hi Alex,

 

thanks for the reply..the requests are now sent as XML. The only problem I have is that the server responds with

"Error processing request stream. Binding to new entities is not supported in PUT operations."


Do you know if the server doesn't support this or if there is another error?

Here is my small hacky sample code ;)

var sMetadataURL = "http://services.odata.org/(S(wj5boqtjql2dfjjcqmfy3i1y))/OData/OData.svc/$metadata";
var sUrl = "http://services.odata.org/(S(wj5boqtjql2dfjjcqmfy3i1y))/OData/OData.svc/Products";

var oHeaders = {};
request = {
headers : oHeaders, // object that contains HTTP headers as name value pairs
requestUri : sUrl, // OData endpoint URI
};

OData.read(sMetadataURL, function (metadata) {
OData.read(request, function (data, response) {
debugger;

var entry = data.results[0];
// modify data
entry.Name = "Doe2";
var updateUrl = entry.__metadata.uri;

oHeaders['Content-Type'] = "application/atom+xml";
oHeaders['DataServiceVersion'] = "2.0";

request = {
headers : oHeaders, // object that contains HTTP headers as name value pairs
requestUri : updateUrl, // OData endpoint URI
method : "PUT", // HTTP method (GET, POST, PUT, DELETE)
data : entry // Payload of the request (in intermediate format)
};

OData.defaultHandler = OData.atomHandler;
OData.request(request, function (data, response) {
debugger;
}, function(err){
alert(err);
}, undefined, undefined, metadata);
}, function(err){
alert(err);
}, undefined, undefined, metadata);
}, function (error) {
alert(error);
}, OData.metadataHandler);

 

It worked when using JSON to do the PUT request.

Another question: In the payload do I have to embed the metadata if I e.g. PUT, POST a new entry or is it sufficient to add the complete metadata document when triggering the request and datajs does the corresponding data formatting etc.? Does datajs really check each property and then checks the metadata document if it contains metadata for this property and does the correct conversion? Or does datajs check if the property has "embedded" metadata and uses that data and if not doesn't use any metadata?

Thank you very much :)

Apr 27, 2012 at 1:08 AM
Edited Apr 27, 2012 at 1:23 AM

Hi Joe,

    For ATOM if you include the metadata document, the library will look for the properties there and set the appropriate types and the magic (you still have to specify __metadata.type for it to work).  Also, if there is metadata about the properties in the payload itself, then that is going to be used instead.  For example if your object looks like this:

{
    __metadata:{
        type:"ns.type",
        properties:{
            p1: {
                type: "Edm.Int32"
            }
       }
   },
   p1: 5000,
   p2: true
}

Then, the library will use the type information found in __metadata for p1; however, it will look into the metadata document to figure out what's the type for p2.

When using JSON the library doesn't do any special processing of the request payload other than date formatting.

About the error, can you post a network trace of the reqeuest??

Regards,

Alex Trigo.

Apr 27, 2012 at 12:38 PM

Hi Alex,

 

thanks for the clarifications. So I get it right that when using JSON the metadata documnent will not be used whereas when using ATOM it is parsed? I thought that in both cases the document is used...

Here is the trace of the PUT request. To test it youself you can simply copy the sample above in a HTML file.

 

 
response body
{
"error": {
"code": "", "message": {
"lang": "en-US", "value": "Error processing request stream. Binding to new entities is not supported in PUT operations."
}
}
}

response header:
Key Value
Response HTTP/1.1 400 Bad Request
Date Fri, 27 Apr 2012 11:32:16 GMT
Content-Type application/json
Server Microsoft-IIS/7.5
Cache-Control private
DataServiceVersion 1.0;
X-AspNet-Version 4.0.30319
X-Powered-By ASP.NET
Proxy-Connection Keep-Alive
Connection Keep-Alive

request header:

Key Value
Request PUT http://services.odata.org/(S(wj5boqtjql2dfjjcqmfy3i1y))/OData/OData.svc/Products(0) HTTP/1.1
Content-Type application/atom+xml
Accept application/atomsvc+xml;q=0.8, application/json;q=0.5, */*;q=0.1
DataServiceVersion 2.0
Referer http://localhost:8080/writetest.html
Accept-Language en
Accept-Encoding gzip, deflate
User-Agent Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
Host services.odata.org
Content-Length 1176
Proxy-Connection Keep-Alive
Pragma no-cache

request body:
<entry xmlns="http://www.w3.org/2005/Atom"
xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
<author>
<name />
</author>
<title type="text">Doe2</title>
<content type="application/xml">
<m:properties>
<d:ID m:type="Edm.Int32">0</d:ID>
<d:ReleaseDate m:type="Edm.DateTime">1992-01-01T00:00:00
</d:ReleaseDate>
<d:DiscontinuedDate m:null="true" m:type="Edm.DateTime" />
<d:Rating m:type="Edm.Int32">4</d:Rating>
<d:Price m:type="Edm.Decimal">2.5</d:Price>
</m:properties>
</content>
<id>http://services.odata.org/(S(wj5boqtjql2dfjjcqmfy3i1y))/OData/OData.svc/Products(0)
</id>
<category term="ODataDemo.Product"
scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<link
rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Category"
href="http://services.odata.org/(S(wj5boqtjql2dfjjcqmfy3i1y))/OData/OData.svc/Products(0)/Category" />
<link
rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Supplier"
href="http://services.odata.org/(S(wj5boqtjql2dfjjcqmfy3i1y))/OData/OData.svc/Products(0)/Supplier" />
<summary type="text">Whole grain bread</summary>
</entry>

 

May 3, 2012 at 12:12 AM

Hi Joe,

   Thanks for the trace it was really helpful.  To clear that out the way, you are getting this issue because you are issuing a PUT and the payload has navigation properties in it. You should do a MERGE request, or massage the entry object above and remove the navigation properties altogether. ... To do such a rquest you should change your code above to:

oHeaders["x-http-method"] = "MERGE";
request = {
    headers : oHeaders, // object that contains HTTP headers as name value pairs
    requestUri : updateUrl, // OData endpoint URI
    method : "POST", // HTTP method (GET, POST, PUT, DELETE)
    data : entry // Payload of the request (in intermediate format)
};

 This will send a MERGE request using http method tunneling.  It has to be done this way because MERGE is not a standard http verb and many http processors (like proxies and the like) might block the non-standard verb.

 To sum it up, in OData PUT means completly replace the entry, and MERGE is do a differential update to the entry.. that is only update those values that are specified and different.

  Now about the metadata.. sorry if I was not clear about it.  When reading a response yes, the metadata document is used to do the appropriate data conversions and feed customizations (if any) in ATOM.  When sending a rquest, only in ATOM the metadata document is used to apply feed customizations if any and set the property types.  When sending JSON requests, the metadata document is not used at all.



Regards,

Alex Trigo.

May 11, 2012 at 11:57 AM

Hi Alex,

  1. In your headers collection, set the content type header to application/atom+xml

do I now also have to add odata=verbose in datajs 1.03 for atom/xml requests?

BTW: what does verbose mean?

 

Thanks!

May 11, 2012 at 11:35 PM

Hi Joe,

   No for atom you don't need to add the odata parameter to the content type.  The verbose is becasue there is going to be eventually a new JSON format in OData V3, so, WCF Data Services 5.0 added that parameter to the mime type to distinguish between the two of them.. and the one currently available is now called JSON verbose.  More info is available here

Regards,

Alex Trigo.

Dec 20, 2012 at 2:38 PM

Hi,

I tried to Delete one data using my Odata service using the DELETE method , there is a

'no handler for data' error returns 

And the error as

{
    "error": {
        "message": {
            "lang": "en-US", "value": "This release of library support only GET (read) request, received a request with method DELETE"
        }
    }
}

can you please help me to solve this issue

Regards
Ratheesh
Coordinator
Dec 21, 2012 at 11:45 PM
Edited Dec 21, 2012 at 11:46 PM

Hi ratheeshkr

what version of datajs are you using and  can you please post a network trace of the request to clarify things more ?

--------

Regards,

Hussein

Dec 27, 2012 at 5:13 AM

Dear Hussein,

Thank you for your response,

I tried this using the datajs version 1.1.0, and datajs version 0.0.3.

Regards

Ratheesh