I am trying not to re-invent the wheel here...
I have found some nice documentation on CalDav sync implementation there
According to its website, DaviCal is rfc6578-compliant since v. 0.9.8 (see here).
I therefore first send my request to get the sync token as follows:
PROPFIND http://my_cal_srv/user/calendar_path HTTP/1.1
Content-Type: application/xml; charset="utf-8"
<?xml version="1.0" encoding="utf-8" ?>
<d:propfind xmlns:d='DAV:'>
<d:prop>
<d:displayname />
<d:sync-token />
</d:prop>
</d:propfind>
This returns data as expected:
<?xml version="1.0" encoding="utf-8" ?>
<multistatus xmlns="DAV:">
<response>
<href>/caldav.php/user/calendar_path/</href>
<propstat>
<prop>
<displayname>My Calendar</displayname>
<sync-token>data:,9</sync-token>
</prop>
<status>HTTP/1.1 200 OK</status>
</propstat>
</response>
</multistatus>
So far so good, I have a token, it's "data: ,9". So, let's just try to get changes since 8, the token I had when I queried the server prior to adding some event.
REPORT http://my_cal_srv/user/calendar_path HTTP/1.1
Content-Type: application/xml; charset="utf-8"
<?xml version="1.0" encoding="utf-8" ?>
<d:sync-collection xmlns:d="DAV:">
<d:sync-token>8</d:sync-token>
<d:sync-level>1</d:sync-level>
<d:prop>
<d:getetag/>
</d:prop>
</d:sync-collection>
The answer is:
<?xml version="1.0" encoding="utf-8" ?>
<multistatus xmlns="DAV:">
<response>
<href>/caldav.php/user/path/86166f9c-3e2e-4242-9a28-0f3bfb1dd67a-caldavsyncadapter.ics</href>
<propstat>
<prop>
<getetag>"5ed2101b0c867e490dbd71d40c7071bb"</getetag>
</prop>
<status>HTTP/1.1 200 OK</status>
</propstat>
</response>
<response>
<href>/caldav.php/user/path/cb354fab-b41d-49ad-8a4f-8d68c9090ea0.ics</href>
<propstat>
<prop>
<getetag>"334892703f4151024e9232eab9b515a7"</getetag>
</prop>
<status>HTTP/1.1 200 OK</status>
</propstat>
</response>
<sync-token>data:,9</sync-token>
</multistatus>
After deleting an entry (so I get sync-token 10, and still compare using token 8), I get following result :
<?xml version="1.0" encoding="utf-8" ?>
<multistatus xmlns="DAV:">
<response>
<href>/caldav.php/user/cal_path/86166f9c-3e2e-4242-9a28-0f3bfb1dd67a-caldavsyncadapter.ics</href>
<status>HTTP/1.1 404 Not Found</status>
</response>
<response>
<href>/caldav.php/user/cal_path/cb354fab-b41d-49ad-8a4f-8d68c9090ea0.ics</href>
<propstat>
<prop>
<getetag>"334892703f4151024e9232eab9b515a7"</getetag>
</prop>
<status>HTTP/1.1 200 OK</status>
</propstat>
</response>
<sync-token>data:,10</sync-token>
</multistatus>
So I am a little confused here as I don't really know how to interpret these results...
Could anybody please explain to me how to extract the sync info from here? It is a little hard to figure out the changes types because the ICS namings are unclear...
Thanks in advance for helping out... And merry X-Mas !
Regards,
N.
That you get a "data:,9" doesn't imply you can actually query "data:,8" or ,7 etc. Sync tokens are opaque and do NOT give you a versioning system (you need sth like DAV Versioning Extensions for that).
DAV sync-tokens are a simple optimization technique - nothing more. They are completely opaque to the client and the server can expire sync tokens at any time (and is not required to save tombstones and such). Eg a server which can't store tombstones can simply expire tokens on DELETE requests.
The way you use sync-tokens is:
to figure out which child collections of a parent collection need to be re-synced
to optimize syncing of a the resources within a child collection
1) Which child collections need to be synced
Assume you have a collection of calendars (e.g. my_cal_srv/user/) and you do a PROPFIND Depth:1 on this collection, asking for the sync-tokens of the child collections. If those don't match the ones of your clients cache anymore, you know you need to perform a sync of just those child collections.
Note: do NOT use the token you got back from this request to sync the child collection (which is what you do above). It might have expired already. Within sync-reports only use tokens you got from sync-reports!
2) Optimizing syncing of the collection contents
Again: sync-token's are an optimization, nothing more. You always need to be prepared to get an (in)valid-sync-token precondition error (which means the server expired the token) and do a full refetch of the collection contents! And then compare that (URL,ETag) to your cached version to figure out what the changes are. (essentially all the steps you need to do when you have a server which doesn't support sync-reports).
If you get a sync-token in the sync-report results, you can then use it in the next sync-request. If the server still has the state, it'll just give you the changes. If it expired the token, it'll give you the sync-token error.
Note: In case it isn't obvious - in the very first sync-request you don't (can't) provide a token. You run the query w/o a token and get back all the contents. You do the same again if the server sends you an (in)valid-sync-token error.
You're not doing a correct request. In your request you have:
<d:sync-token>8</d:sync-token>
But this should be:
<d:sync-token>data:,8</d:sync-token>
Aside from that, the first response you are getting tells you that:
These resources have been changed or newly created:
/caldav.php/user/path/86166f9c-3e2e-4242-9a28-0f3bfb1dd67a-caldavsyncadapter.ics
/caldav.php/user/path/cb354fab-b41d-49ad-8a4f-8d68c9090ea0.ics
The second response tells you:
This resource has been changed or newly created:
/caldav.php/user/cal_path/cb354fab-b41d-49ad-8a4f-8d68c9090ea0.ics
This resource has been deleted:
/caldav.php/user/cal_path/86166f9c-3e2e-4242-9a28-0f3bfb1dd67a-caldavsyncadapter.ics
Related
I need to get the ID's of the records in a cross-reference field using Web API. Is there an API method to solve this type of task? Or at least I want to know, how to get the value of a specific field?
There are many different methods described in the documentation for operating with list fields (such as GetValuesListValue) and I wonder if there a same way to solve my task.
I can use ExecuteSeach method, but it isn't very convenient.
Alexander, you can either use the REST or Webservices APIs.
REST APIs
Using the Get content by id, /api/core/content/*contentid*
Then you can pass OData to just get the field (id) contents by passing the following in the body
{"Value":"?$filter=FieldId eq '*field id of cross-reference field*'"}
Webservices APIs
You can call the /ws/record.asmx GetRecordById passing the following
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchemainstance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<GetRecordById xmlns="http://archer-tech.com/webservices/">
<sessionToken>session token</sessionToken>
<moduleId>int</moduleId>
<contentId>int</contentId>
</GetRecordById>
</soap:Body>
</soap:Envelope>
Then you'd have to iterate through the returned XML to get the field contents.
Sample response below. I want to check the existence of a specific error code (860) in the response below. Technically, to avoid picking the error up accidentally in a reference number, I need to be checking it is in the bit labelled < code >860< /code > (inserted spaces so it would show).
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:activatePortResponse xmlns:ns2="http://transferobjects.abc.abc.org">
<return som="6001365" state="Approved">
<errors>
<error>
<code>860</code>
<description>The Port cannot be activated outside the ready for service dateTime window (grace period taken into account).</description>
<mnemonic>RFS_WINDOW</mnemonic>
</error>
<name>som</name>
</errors>
<success>false</success>
</return>
</ns2:activatePortResponse>
</soap:Body>
</soap:Envelope>
I was trying to build a set of calls with expected error results to check the the error responses are returned as they should. Going through all the usual garbage messages that meant nothing to me, I just kept tweaking.
Turned out I could use a Contains method and just paste in more, rather than just 860 or even < code >860< /code > I just had to paste in a bigger chunk like this:
<error>
<code>860</code>
<description>The Port cannot be activated outside the ready for service dateTime window (grace period taken into account).</description>
<mnemonic>RFS_WINDOW</mnemonic>
</error>
So I have a solution, but if anyone wants to show me how to do it with XPath, in a less hamfisted way, that would be cool.
You could do an XPath Match assertion with the following expression //error/code, which in the above response message would find 860. This way you know that this 860 has been found at a particular place in the XML hierarchy.
I'm using some additional logic to skirt around this issue, but I've noticed reportPlaySeconds being called regardless of the interval value I return.
The Result documentation states:
interval string(128) - Number of seconds to elapse before next report. Note: A value of 0 indicates that no reporting after the start of playback of that track should be issued.
This is an example request request:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.sonos.com/Services/1.1">
<SOAP-ENV:Header>
<ns1:credentials>
<ns1:deviceId>00-01-02-0A-0B-0C</ns1:deviceId>
<ns1:deviceProvider>Sonos</ns1:deviceProvider>
<ns1:sessionId>303-TEMP</ns1:sessionId>
</ns1:credentials>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ns1:reportPlaySeconds>
<ns1:id>track_id</ns1:id>
<ns1:seconds>0</ns1:seconds>
</ns1:reportPlaySeconds>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
And the response:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.sonos.com/Services/1.1">
<SOAP-ENV:Body>
<ns1:reportPlaySecondsResponse>
<ns1:reportPlaySecondsResult>
<ns1:interval>0</ns1:interval>
</ns1:reportPlaySecondsResult>
</ns1:reportPlaySecondsResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
If I've understood the documentation correctly, returning <ns1:interval>0</ns1:interval> means reportPlaySeconds shouldn't be called again. I'm also using setPlayedSeconds to calculate more granular reporting, so additional reportPlaySeconds calls are unnecessary.
Any ideas?
Although the documentation does state you (the provider) can change the reporting interval by returning interval in the reportPlaySecondsResult, the feature is not enabled in firmware as of the latest release (Version 5.4, Build 29.5-91030, Released 13 July 2015).
As you have seen, the player continues to report on a fixed interval no matter what the value returned in reportPlaySecondsResult.
I've opened a ticket with the documentation team for an update.
Anyone out there with experience with the Ebay API? I'm essentially trying to list all items for one shop on their website, so it's not going to be a public service usage. The GetSellerList method seems to be the way to go, but the documentation on the Ebay Website itself is very scant and not really well done at all.
http://developer.ebay.com/DevZone/XML/docs/reference/ebay/GetSellerList.html
I'm in the process of trying out the code samples and the problem I'm hitting now is whether or not I need a UserToken or not. #PITA
Thanks,
Here is about the minimum request I used that worked for me:
<?xml version="1.0" encoding="utf-8"?>
<GetSellerListRequest xmlns="urn:ebay:apis:eBLBaseComponents">
<RequesterCredentials>
<eBayAuthToken>--Enter your AuthToken here--</eBayAuthToken>
</RequesterCredentials>
<ErrorLanguage>en_US</ErrorLanguage>
<WarningLevel>High</WarningLevel>
<StartTimeFrom>2013-06-01T21:59:59.005Z</StartTimeFrom>
<StartTimeTo>2013-09-26T21:59:59.005Z</StartTimeTo>
<EndTimeFrom>2013-09-26</EndTimeFrom>
<EndTimeTo>2013-11-26</EndTimeTo>
<GranularityLevel>Coarse</GranularityLevel>
<UserID>--Enter your seller's name here--</UserID>
<Pagination>
<EntriesPerPage>200</EntriesPerPage>
<PageNumber>1</PageNumber>
</Pagination>
<OutputSelector>ItemArray.Item.ItemID</OutputSelector>
<OutputSelector>ItemArray.Item.Quantity</OutputSelector>
<OutputSelector>ItemArray.Item.Title</OutputSelector>
<OutputSelector>ItemArray.Item.PrimaryCategory.CategoryID</OutputSelector>
<OutputSelector>ItemArray.Item.PrimaryCategory.CategoryName</OutputSelector>
</GetSellerListRequest>
I also had to add these headers to the request:
X-EBAY-API-APP-NAME -- Add yours here --
X-EBAY-API-CALL-NAME GetSellerList
X-EBAY-API-REQUEST-ENCODING XML
X-EBAY-API-SITEID 0
X-EBAY-API-DEV-NAME -- Add yours here --
X-EBAY-API-CERT-NAME -- Add yours here --
X-EBAY-API-COMPATIBILITY-LEVEL 825
I'm not sure which of the "-- Add yours here --" entries are public and which are private, so I'll aire on the side of caution and I'll let you get them for yourself.. :-)
With no eBayAuthToken entered, you get the following error:
<Errors>
<ShortMessage>Auth token is invalid.</ShortMessage>
<LongMessage>Validation of the authentication token in API request failed.</LongMessage>
<ErrorCode>931</ErrorCode>
<SeverityCode>Error</SeverityCode>
<ErrorClassification>RequestError</ErrorClassification>
</Errors>
I hope this helps.
<?xml version="1.0" encoding="utf-8"?>
<GetSellerListRequest xmlns="urn:ebay:apis:eBLBaseComponents">
<RequesterCredentials>
<eBayAuthToken>$authToken</eBayAuthToken>
</RequesterCredentials>
<ErrorLanguage>en_US</ErrorLanguage>
<WarningLevel>High</WarningLevel>
<StartTimeFrom>2015-01-01T00:00:00.005Z</StartTimeFrom>
<StartTimeTo>2015-03-31T23:59:59.005Z</StartTimeTo>
<EndTimeFrom>2015-03-31T23:59:59.005Z</EndTimeFrom>
<EndTimeTo>2015-05-31T23:59:59.005Z</EndTimeTo>
<GranularityLevel>Coarse</GranularityLevel>
<UserID>----testuser----</UserID>
<Pagination>
<EntriesPerPage>200</EntriesPerPage>
<PageNumber>1</PageNumber>
</Pagination>
<OutputSelector>ItemArray.Item.ItemID</OutputSelector>
<OutputSelector>ItemArray.Item.Quantity</OutputSelector>
<OutputSelector>ItemArray.Item.Title</OutputSelector>
<OutputSelector>ItemArray.Item.PrimaryCategory.CategoryID</OutputSelector>
<OutputSelector>ItemArray.Item.PrimaryCategory.CategoryName</OutputSelector>
</GetSellerListRequest>
Header Request Values
$headers = array(
'X-EBAY-API-SITEID:'.SITEID,
'X-EBAY-API-CALL-NAME:GetSellerList',
'X-EBAY-API-REQUEST-ENCODING:'.RESPONSE_ENCODING,
'X-EBAY-API-COMPATIBILITY-LEVEL:' . API_COMPATIBILITY_LEVEL,
'X-EBAY-API-DEV-NAME:' . API_DEV_NAME,
'X-EBAY-API-APP-NAME:' . API_APP_NAME,
'X-EBAY-API-CERT-NAME:' . API_CERT_NAME,
'Content-Type: text/xml;charset=utf-8'
);
I am trying to test my ability to import TimeActivity records and even when using the sample Create Request XML for TimeActivity I get an error:
Apache Tomcat/7.0.23 - Error report HTTP Status 400 - type Status reportmessage description The request sent by the client was syntactically incorrect ().Apache Tomcat/7.0.23
below is my sample xml create request (pulled from https://developer.intuit.com/docs/0025_quickbooksapi/0050_data_services/v2/0400_quickbooks_online/timeactivity)
<?xml version="1.0" encoding="utf-8"?>
<TimeActivity xmlns:ns2="http://www.intuit.com/sb/cdm/qbo" xmlns="http://www.intuit.com/sb/cdm/v2">
<TxnDate>2011-08-03-07:00</TxnDate>
<NameOf>Vendor</NameOf>
<Vendor>
<VendorIdidDomain="QBO">3793</VendorId>
</Vendor>
<CustomerId>3794</CustomerId>
<ItemId>3</ItemId>
<ClassId>1</ClassId>
<StartTime>2011-08-30T11:45:00-07:00</StartTime>
<EndTime>2011-08-30T13:15:00-07:00</EndTime>
<Taxable>true</Taxable>
<HourlyRate>10.5</HourlyRate>
<BillableStatus>Billable</BillableStatus>
<Hours>10</Hours>
<Minutes>5</Minutes>
<Description>This is a Description</Description>
</TimeActivity>
What am I doing wrong here?
Sharing a sample TimeActivity create request. Please check other reference attributes like Vendor, Class etc. It should work.
<?xml version="1.0" encoding="utf-8"?>
<TimeActivity xmlns='http://www.intuit.com/sb/cdm/v2'>
<TxnDate>2012-08-30-07:00</TxnDate>
<NameOf>Employee</NameOf>
<Employee>
<EmployeeId>11</EmployeeId>
</Employee>
<CustomerId>2</CustomerId>
<JobId>4</JobId>
<BillableStatus>Billable</BillableStatus>
<HourlyRate>50.0</HourlyRate>
<StartTime>2012-08-30T11:45:00-07:00</StartTime>
<EndTime>2012-08-30T13:15:00-07:00</EndTime>
<Description/>
</TimeActivity>
There should be couple of small changes in the sample request ( We will update the doc )
<?xml version="1.0" encoding="utf-8"?>
<TimeActivity xmlns:ns2="http://www.intuit.com/sb/cdm/qbo" xmlns="http://www.intuit.com/sb/cdm/v2">
<NameOf>Vendor</NameOf>
<Vendor>
<VendorId idDomain="QBO">5</VendorId>
</Vendor>
<CustomerId>2</CustomerId>
<ItemId>3</ItemId>
<Taxable>true</Taxable>
<HourlyRate>10.5</HourlyRate>
<BillableStatus>Billable</BillableStatus>
<Hours>10</Hours>
<Minutes>5</Minutes>
<Description>This is a Description</Description>
</TimeActivity>
First replace all the reference values with the same of your test data.
For ex - VendorId, Class, Item and Customer
There are two bugs in the sample request.
1. There should be a space between 'VendorId' and 'idDomain' ( Ref -5th line of the req )
2. According to the doc, " Either method of indicating duration can be entered, but not both. Hours/Minutes OR StartTime/EndTime is required."
So plz remove any one of these. ( I've removed StartTime/EndTime )
Otherwise you'll get the error which you have mentioned above.
That is - Response code 400, Error msg - TIME_ACTIVITY_MULTIPLE_DURATION_TYPES_PRESENT
Please let us know if the above changes work for you.
I tried the same XML in Api Explorer. It worked fine for me. PFB snapshot. Please check if you are facing any encoding issue.
Please let me know if it works for you.