Start a siteSync programatically
I want to start a siteSync programatically when some other event happens.
I am working on version 6.3
I've been trying to make it work by use of the /sitefinity/services/sitesync/sitesyncservice.svc
I initially tried to use the class that the service itself uses, but could not find it...
Service="Telerik.Sitefinity.Modules.SiteSync.Web.SiteSyncService" (where is this ???)
so my next attempt was to make an http post to sitesyncservice.svc/StartSync with the json object that I got from a manual sync thru chrome's developer tools
it goes something like this:
"Types":["Telerik.Sitefinity.Events.Model.Calendar","Telerik.Sitefinity.Events.Model.Event","Telerik.Sitefinity.Taxonomies.Model.Taxonomy","Telerik.Sitefinity.Taxonomies.Model.Taxon","Telerik.Sitefinity.GenericContent.Model.ContentItem","Telerik.Sitefinity.Libraries.Model.DocumentLibrary","Telerik.Sitefinity.Libraries.Model.Document","Telerik.Sitefinity.Forms.Model.FormDescription","Telerik.Sitefinity.Libraries.Model.Album","Telerik.Sitefinity.Libraries.Model.Image","Telerik.Sitefinity.Lists.Model.List","Telerik.Sitefinity.Lists.Model.ListItem","Telerik.Sitefinity.News.Model.NewsItem","Telerik.Sitefinity.Pages.Model.PageTemplate","Telerik.Sitefinity.Pages.Model.PageNode","Telerik.Sitefinity.Libraries.Model.VideoLibrary","Telerik.Sitefinity.Libraries.Model.Video","Telerik.Sitefinity.Pages.Model.ControlPresentation"],
"TypeFilters":null,
"Schedule":null,
"ServerId":"<receiving serverId here, from SiteSyncConfig.config>",
"UserId":"00000000-0000-0000-0000-000000000000",
"SummaryId":"00000000-0000-0000-0000-000000000000",
"TotalItemsCount":0,
"IsStopRequested":false
this was giving me (401) unauthorized, I added basic authentication with the account that I set up at the receiving instance, and then it gives me (403) forbidden.
I tried doing a /RequestValidation first like the backend UI does, but that call is also giving me the (403) forbidden.
If anyone can help, it would be greatly appreciated.
Hi Ernesto,
Public SiteSync API has not been fully developed and so for the time being we do not have any documentation on it. However there are some ways you can take advantage of the already available implementations. Please find the attached archive that consists of an excerpt with an example on how you can trigger syncing through API. Please note this is still work in progress and it might be changed in future. I would also suggest to test this on a safe environment.
Regards,
Pavel Benov
Telerik
Thank you Pavel,
I tried the approach that you provided in the word document, but I could not find the SiteSync facade for App.WorkWith() ...
Somehow on version 6.3.5000 it is done differently because the physical DLL Telerik.Sitefinity.SiteSync does not exist, so the classes must be in some other DLL but I have not been able to find them.
Hi Ernesto,
Sorry for my previous response. I forgot to mention this is introduced in Sitefinity 7.0+ versions. You could try a test upgrade in order to try out the API. Any further feedback you can give us is highly appreciated.
Regards,
Pavel Benov
Telerik
So I upgraded to version 7.0.
SiteSync broke, clicking on "Test Connection" did nothing, so I removed the receiving server to add it back again.
and when clicking "Add this server"
url http://<sending site>/Sitefinity/Services/SiteSync/SiteSyncService.svc/RequestTargetSites/?url=<receiving site>&userName=<username>&password=<password>&provider=&unv_tstmp_prn=140355555555
comes back with a 404 not found.
I am not sure how to go about to fix this...
I got it :D
looks like it will sync, fingers crossed....
I had to take the new SiteSyncService.svc file from a 7.0 install and copy it over the version I had in my instance (6.3), normally I just copy over everything in the bin folder for an upgrade, I'll see if any other service files are needed.
This part changed
Service="Telerik.Sitefinity.SiteSync.Web.SiteSyncService"
Hi Ernesto,
I am glad you were able to overcome the problem. Do not hesitate to write back if any further complications may arise.
Regards,
Pavel Benov
Telerik
Hello Pavel,
I am now on version 7.0 and trying to kick a sync programatically.
I am following the code you provided in the word document, but am getting a fatal error
[7/28/2014 11:41:28 PM] Sync task 376aaf60-81b5-64c2-a3a8-ff0000665429 encountered a fatal error:<
br
>System.NullReferenceException: Object reference not set to an instance of an object.<
br
> at Telerik.Sitefinity.SiteSync.SyncingManager.InitializeSummary(DateTime startTime, SiteSyncExportContext context)<
br
> at Telerik.Sitefinity.SiteSync.SyncingManager.InitializeSync(SiteSyncExportContext context)<
br
> at Telerik.Sitefinity.SiteSync.SyncingManager.Sync(SiteSyncExportContext context)<
br
> at Telerik.Sitefinity.SiteSync.SiteSyncTask.ExecuteTask()
this is the code I am calling
string[] typesToSync = new string[] "Telerik.Sitefinity.Pages.Model.PageNode" ;
using (var sync = App.WorkWith().SiteSync())
sync.SelectDefaultTarget().Sync(typesToSync);
I had all the types in the string array, with the same error.
There are not much members I can play with on these facade objects so I do not know what to do...
Since there is no documentation I can find, I am relying on you to solve this quickly.
Thanks for the prompt response.
Some other information:
I can do a sync manually just fine. The sync throws some fails and other successes, but programatically, looks like it does not even start because of the "reference not set to an instance of an object".
I have just one receiving server in my configuration.
Hi Ernesto,
Unfortunately Pages are not synced with the current state of the SiteSync API. You will have to use the UI for syncing PageNode, PageData etc. objects.
Regards,
Pavel Benov
Telerik
@Pavel, you sent me a word document (attached on earlier post in this thread) with code to start a sync programmatically...
Was this functionality hidden/taken-off and that is why it is not available anymore ?
Can I somehow emulate what the UI does and start a sync with some code?
Hi Ernesto,
As I have said in my reply from 05.07.2014 this is still a work in progress. Although available as API in 7.0 it is not officially announced and therefore not supported. This is basically a Beta version of the SiteSync API and will be further developed and modified, extended etc. We will announce it officially when it is ready and fully tested. We will also provide code samples in our Documentation, but for now you can only use the calls for content such as News, Events etc.
Regards,
Pavel Benov
Telerik
@Pavel, do you know if the status of this changed with version 7.2 ?
Hello Ernesto,
Our dev team is putting all efforts into enhancing our core modules, so there is currently no progress on the anticipated SiteSync API official introduction.
You can keep tracking our General Discussions thread for our latest implementations and also our Product Roadmap section.
Regards,
Vassil Vassilev
Telerik
Ernesto,
With the latest version of SiteFinity, does it FINALLY allow a single sync operation to sync to multiple production sites? We have one staging environemnt that we have to sync to THREE production sites that are geolocated. The scheduler is useless as it only allows you to sync to one site. Has anything changed with respect to this in Sitefinity 7+? This is basic function that I would expect a CMS system like Sitefinity to support.
Hello Andrew,
You cannot sync data to multiple nodes with one sync in our latest release.
Currently you have to change the destination after each sync in order to have all up-to-date.
Regards,
Vassil Vassilev
Telerik
Hello aceven24,
I am posting the code I use on my 7.0 instances
001.
namespace
Web.Listeners
002.
003.
public
class
SyncHacker
004.
005.
public
static
string
LogCategory =
"SyncHacker"
;
006.
007.
//TODO: test passing session into syncNow, a way for the listener to grab a hold of session object.
008.
009.
public
static
bool
SyncNow()
010.
011.
// kick-off a sync, or a set of sync, one for each receiving server
012.
LogManager.Write(LogCategory,
"sync task should execute now :)"
);
013.
014.
if
(HttpContext.Current !=
null
&& HttpContext.Current.Session !=
null
)
015.
016.
LogManager.Write(
"session-id"
, HttpContext.Current.Session.SessionID);
017.
018.
else
019.
020.
LogManager.Write(
"session-id"
,
"session is null :("
);
021.
022.
023.
string
url = ConfigOptions.GetValue(
"siteSync/service/startSync/endpoint"
,
""
);
024.
LogManager.Write(LogCategory,
string
.Format(
" url: [0]"
, url));
025.
string
json = ConfigOptions.GetValue(
"siteSync/service/startSync/post"
,
string
.Empty);
026.
027.
string
urlv = ConfigOptions.GetValue(
"siteSync/service/requestValidation/endpoint"
,
""
);
028.
029.
XmlNode servers = ConfigOptions.GetNode(
"siteSync/service/startSync/servers"
);
030.
if
(servers ==
null
)
031.
032.
LogManager.Write(LogCategory,
"No receiving servers configured in siteSync/service/startSync/servers"
);
033.
return
false
;
034.
035.
036.
foreach
(XmlNode svr
in
servers.ChildNodes)
037.
038.
039.
string
svrUser =
"sync"
;
040.
XmlAttribute usrAttr = svr.Attributes[
"user"
];
041.
if
(usrAttr !=
null
) svrUser = usrAttr.Value;
042.
043.
string
svrPwd =
"password"
;
044.
XmlAttribute pwdAttr = svr.Attributes[
"pwd"
];
045.
if
(pwdAttr !=
null
) svrPwd = pwdAttr.Value;
046.
047.
//string validate = PostJsonToUrl(urlv, json.Replace("#serverId#", svr.InnerText), new System.Net.NetworkCredential(svrUser, svrPwd));
048.
//LogManager.Write(LogCategory, string.Format(" validation [0][1]", svr.InnerText, validate));
049.
string
response = PostJsonToUrl(url, json.Replace(
"#serverId#"
, svr.InnerText),
new
System.Net.NetworkCredential(svrUser, svrPwd));
050.
LogManager.Write(LogCategory,
string
.Format(
" startSync [0][1]"
, svr.InnerText, response));
051.
052.
053.
054.
055.
056.
057.
return
true
;
058.
059.
060.
061.
private
static
string
getSessionIdCookieValue()
062.
063.
return
"abcdefghijklmnopqrstuvwxyz"
;
064.
065.
066.
private
static
string
PostJsonToUrl(
string
url,
string
json, NetworkCredential credentials =
null
)
067.
068.
HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(url);
069.
myRequest.Method =
"POST"
;
070.
071.
//myRequest.UserAgent = _userAgent;
072.
myRequest.Timeout = 30000;
073.
074.
if
(credentials !=
null
)
075.
076.
string
basedAccount =
string
.Format(
"0:1"
, credentials.UserName, credentials.Password).ToBase64();
077.
myRequest.Headers.Add(
"Authorization"
,
string
.Format(
"Basic 0"
, basedAccount));
078.
079.
080.
myRequest.ContentType =
"application/json"
;
081.
//myRequest.Headers.Add("Accept-Language", "en-US,en;q=0.8,fr-CA;q=0.6,fr;q=0.4,es;q=0.2,zh-CN;q=0.2");
082.
myRequest.Accept =
"application/json"
;
083.
myRequest.Headers.Add(
"Cache-Control"
,
"no-cache"
);
084.
085.
string
cookieDomain = ConfigOptions.GetValue(
"siteSync/cookie/domain"
,
"yourwebsite.com"
);
086.
087.
myRequest.CookieContainer =
new
CookieContainer();
088.
myRequest.CookieContainer.Add(
new
Cookie(
"ASP.NET_SessionId"
, getSessionIdCookieValue(),
string
.Empty, cookieDomain));
089.
090.
Encoding encoding = Encoding.UTF8;
091.
myRequest.ContentLength = encoding.GetByteCount(json);
092.
Stream stream = myRequest.GetRequestStream();
093.
stream.Write(encoding.GetBytes(json), 0, encoding.GetByteCount(json));
094.
stream.Close();
095.
096.
string
result =
string
.Empty;
097.
098.
try
099.
100.
long
startTicks = DateTime.Now.Ticks;
101.
WebResponse myResponse = myRequest.GetResponse();
102.
StreamReader sr =
new
StreamReader(myResponse.GetResponseStream(), System.Text.Encoding.UTF8);
103.
result = sr.ReadToEnd();
104.
sr.Close();
105.
myResponse.Close();
106.
long
endTicks = DateTime.Now.Ticks;
107.
108.
catch
(Exception ex)
109.
110.
return
ex.Message;
111.
112.
113.
return
result;
114.
115.
116.
The code is looking for data from an XML (you need to code ConfigOptions.GetValue(xpath) that will read the xml)
the xml looks like this:
01.
<
siteSync
>
02.
<
syncOnPublish
>true</
syncOnPublish
>
03.
<
cookie
>
04.
<
domain
>yourwebsite.com</
domain
>
05.
</
cookie
>
06.
<
service
>
07.
<
requestValidation
>
08.
<
endpoint
>http://yourwebsite.com/Sitefinity/Services/SiteSync/SiteSyncService.svc/RequestValidation/<;/
endpoint
>
09.
</
requestValidation
>
10.
<
startSync
>
11.
<
endpoint
>http://yourwebsite.com/Sitefinity/Services/SiteSync/SiteSyncService.svc/StartSync/<;/
endpoint
>
12.
<
servers
>
13.
<
add
user
=
"syncAccount"
pwd
=
"password"
>1ab18b8d-735f-4c9f-xxxx-8428131fe86c</
add
>
14.
</
servers
>
15.
<
post
>
16.
<![CDATA[
17.
"Types":[
18.
"Telerik.Sitefinity.Events.Model.Calendar",
19.
"Telerik.Sitefinity.Events.Model.Event",
20.
"Telerik.Sitefinity.Taxonomies.Model.Taxonomy",
21.
"Telerik.Sitefinity.Taxonomies.Model.Taxon",
22.
"Telerik.Sitefinity.GenericContent.Model.ContentItem",
23.
"Telerik.Sitefinity.Libraries.Model.DocumentLibrary",
24.
"Telerik.Sitefinity.Libraries.Model.Document",
25.
"Telerik.Sitefinity.Forms.Model.FormDescription",
26.
"Telerik.Sitefinity.Libraries.Model.Album",
27.
"Telerik.Sitefinity.Libraries.Model.Image",
28.
"Telerik.Sitefinity.Lists.Model.List",
29.
"Telerik.Sitefinity.Lists.Model.ListItem",
30.
"Telerik.Sitefinity.News.Model.NewsItem",
31.
"Telerik.Sitefinity.Pages.Model.PageTemplate",
32.
"Telerik.Sitefinity.Pages.Model.PageNode",
33.
"Telerik.Sitefinity.Libraries.Model.VideoLibrary",
34.
"Telerik.Sitefinity.Libraries.Model.Video",
35.
"Telerik.Sitefinity.Pages.Model.ControlPresentation"
36.
],
37.
"TypeFilters":null,
38.
"Schedule":null,
39.
"ServerId":"#serverId#",
40.
"UserId":"00000000-0000-0000-0000-000000000000",
41.
"SummaryId":"00000000-0000-0000-0000-000000000000",
42.
"TotalItemsCount":0,
43.
"IsStopRequested":false
44.
]]>
45.
</
post
>
46.
</
startSync
>
47.
</
service
>
48.
</
siteSync
>
notice on the servers/add list, that GUID is taken from the SiteSyncConfig.config file, you can add more servers there and the SyncHacker will loop on them.
Feel free to ask me about the code in this thread.
Hello Ernesto,
Thank you very much for sharing this with the community!
Regards,
Vassil Vassilev
Telerik