With the release of WebSync version 3, we have unfortunately had to made some changes that break backwards compatibility with WebSync 2.
We hesitated when doing this, but in the end, we decided the need to improve our features and fix certain inconsistencies was worth the cost of complete backwards compatibility.
We did strive to keep backwards compatibility wherever possible. When we couldn't, we wrote it down, and the result is this migration guide.
We've done our best to make the upgrade to WebSync 3 as painless as possible; please contact us if you run into trouble.
.NET |
JavaScript |
PHP |
With WebSync 3, many of the fundamental changes are under the hood; better performance, better use of threadpooling, and reduced overhead. However, there were a number also a number of API changes. These API changes included:
We've outlined all the breaking changes below. It may seem like a lot, but really most of the changes are naming changes that take 2 seconds to adjust.
If you run into any problems, please drop us a line!
| WebSync 2 | WebSync 3 | Description |
|---|---|---|
| HandlerEvent | WebSyncEvent | This attribute now explicitly declares the method as a WebSync event handler, as opposed to generically describing it as a "handler" event. |
| HandlerEventType | EventType | Rather than describing how WebSync will continue, as it did previously, this attribute now properly describes how the method will execute. This makes more sense, since the attribute describes the method, not the invoker. |
| HandlerEventType.[XYZ] | EventType.[XYZ] | The name has been simplified, but the purpose is identical in WebSync 3 as compared to WebSnyc 2. |
| HandlerEventType.BeforeDirect[XYZ] / HandlerEventType.AfterDirect[XYZ] | EventType.Before[XYZ] / EventType.After[XYZ] | The BeforeDirect[XYZ] event has been merged with the Before[XYZ[ event. To determine if the event was triggered by the server (which is the case when using the static request handler methods directly), you can check the Source property of the WebSyncEventArgs argument. |
| HandlerEventType.IdleDisconnect | EventType.Disconnect | The IdleDisconnect event has been merged with the Disconnect event. To determine if the disconnect occurred because the client idled out, you can check the Source property of the WebSyncEventArgs argument. |
| HandlerEventContinue | Execution | Rather than describing how WebSync will continue, as it did previously, the attribute now properly describes how the method will execute. This makes more sense, since the attribute describes the method not the invoker. |
| HandlerEventContinue.Immediate | Execution.FireAndForget | Previously, handlers could execute asyncronously using the HandlerEventContinue.Immediate option. The same can be achieved in WebSync 3 through the use of the Execution.FireAndForget option. |
| HandlerEventContinue.OnComplete | Execution.Normal | Previously, syncronous method execution was dependent on setting EventContinue.OnComplete and calling e.Complete(). This is no longer the case. With WebSync 3, the default behaviour is to wait for the specified method to complete execution before processing any further within WebSync, allowing you to pre-process (and deny/allow/etc) the message. |
| HandlerEventArgs | WebSyncEventArgs | Don't worry, almost all your properties are still the same, with 2 minor exceptions ("Data" is "DataJson" and "Ext" is "MetaJson"). This change allowed us to 1) explicitly define the arguments as WebSync related, and 2) exclude the unnecessary elements detailing the underlying communication, which if modified could have unintended side effects. |
| HandlerEventArgs.Data | WebSyncEventArgs.DataJson | To avoid ambiguity, WebSync 3 explicitly states that the Data value should be a JSON string. It will also validate that the value is valid JSON when you set it. |
| HandlerEventArgs.Ext | WebSyncEventArgs.MetaJson | Previously, any values were allowed in the Ext field. To support arbitrary extensions, and disallow invalid JSON strings, the new "MetaJson" value is used. If you were setting the "Ext" field in WebSync 2 to an arbitrary value, simply wrap your value with a call to JSON.Serialise(myValue) to make it valid JSON. |
| RequestHandler.Direct[XYZ] | RequestHandler.[XYZ] | In WebSync 2, events triggered by the server could be distinguished through the use of the "Direct" prefix. This is no longer necessary, as events contain a Source property that contain this information. Therefore, the redundant prefix was removed. |
| GetClientIDs | GetSubscribedClientIDs | To clarify its purpose, this method was renamed. It's functionality has remained the same. |
We've also cleaned up the clutter in the web.config! What clutter, you say? Well, for those of you who got under the hood of what you could configure in WebSync 2, you probably noticed that you could mess things up if you weren't careful. But never fear, WebSync 3 is here, with cleaner configuration options!
Please note that with WebSync 3, the underlying storage providers have been abstracted out. That means that settings that are specific to a specific WebSync provider (such as connection strings for the SQL provider, or Azure connection details for the Azure provider) now reside in a <providerSettings> sub-element beneath the <server> section of the WebSync web.config entry.
First of all, the name of the type used in the WebSync configSection has changed:
| WebSync 2 | WebSync 3 | Description |
|---|---|---|
| FM.WebSync.Core.Config.WebSyncConfig, FM.WebSync.Core | FM.WebSync.Server.Config, FM.WebSync.Server | Well, it's a WebSync Server configuration, so it now resides in the WebSync Server namespace. Makes sense, right? |
In addition to changing the type name, some of the settings have been moved and/or renamed. Provider-specific settings now exist in a <providerSettings> sub-section.
Finally, some of the timing values that were previously available are now automatically calculated based on other values you have set. The same resulting setups are all possible with WebSync 3, but without the possibility of conflicting values.
| WebSync 2 | WebSync 3 | Description |
|---|---|---|
| ipSecurity | N/A | An experimental feature, ipSecurity turned out to be too unreliable to continue using and has been removed. Instead, randomized, large ids are now used to improve security for each client. |
| connectionStringName | providerSettings / connectionStringName | With WebSync 2, the SQL provider was a top-level element. With WebSync 3, providers are much more generic, and as such the connectionStringName is no longer a top-level setting. Instead, it should be embedded at the provider level, like so:
<WebSync>
<server providerType="FM.WebSync.Server.Providers.Sticky.SqlProvider">
<providerSettings>
<add name="connectionStringName" value="WebSync3" />
</providerSettings>
</WebSync>
|
| all timing settings | all timing settings | The timing settings have been adjusted heavily in WebSync 3. Rather than detailing them all here, please simply review the API documentation. |
Almost all error messages have been left unchanged. There are two exceptions: we removed one error code and updated another. The text on any of the error codes may have changed; for details, check the API documentation. In addition, several new error codes have been added; again, see the API documentation for details.
| Previous Value | New Value | Description |
|---|---|---|
| 608 | N/A | Previously used for ipSecurity, this value has been removed. |
| 603 | 801 | 603 errors previously were the generic errors tied to messages that were failed by setting the successful flag to false. These errors have been moved to the 800 range to make it more explicit that these are custom errors. |
The .NET publisher underwent very few changes. The primary difference from WebSync 2 to WebSync 3 is the return type when calling Publisher.Publish and its various overloads.
With WebSync 2, an "out" parameter was used to get an error messages, and the method returned a boolean indicating success or failure. This was terrible. WebSync 3 now returns a Publication object, which includes all the information about the publish attempt, including success or failure, and a nice ToJson() method for easy serialization.
The .NET proxy has been updated to be much more powerful; you now have access to a before, during, and after event. This allows you to 1) modify the messages, and deny as appropriate, 2) set any HTTP settings you desire, and 3) inspect the returned values prior to final delivery to the client.
There were several additions to the proxy, but the only actual change is that he "callback" method that was previously passed to the proxy invocation is now the OnBeforeProxy property of the ProxyInvokeArgs class, an instance of which is passed to the proxy invocation.
Proxy.Invoke(new ProxyCallback((args) =>
{
foreach (Message message in args.Messages) // messages come in as array
{
// deserialize, modify, then reserialize the data
Data data = JSON.Deserialize<Data>(message.Data);
data.Text = data.Text.ToUpperInvariant();
message.Data = JSON.Serialize(data);
}
}));
Proxy.Invoke(new ProxyInvokeArgs()
{
DomainKey = "11111111-1111-1111-1111-111111111111", // replace with your private key
OnBeforeProxy = (args) =>
{
// deserialize, modify, then reserialize the data
Data data = JSON.Deserialize<Data>(message.DataJson);
data.Text = data.Text.ToUpperInvariant();
message.DataJson = JSON.Serialize(data);
}
});
The .NET client underwent the most significant API changes. With WebSync 2, the .NET client support the basic operations: you could connect, subscribe, and publish. However, it was not easy to use, and did not lend itself to a very "natural" code flow.
Therefore, the WebSync 3 .NET client was completely rewritten. It now exposes the underlying HTTP connection, supports synchronous and asynchronous usage patterns, and has a much more logical API. In fact, it now works almost identically to the way the JavaScript client works.
The changes to the .NET client are rather extensive, and best illustrated through a full example:
Client client = new Client("http://example.com/request.ashx");
client.ConnectCompleted += new EventHandler<ConnectCompletedEventArgs>(ConnectCompleted);
client.SubscribeCompleted += new EventHandler<SubscribeCompletedEventArgs>(SubscribeCompleted);
client.Receive += new EventHandler<ReceiveEventArgs>(Receive);
client.Connect();
void ConnectCompleted(object sender, ConnectCompletedEventArgs e)
{
if (e.Error)
{
if(e.Stream)
{
// handle stream failure
}else{
// handle connect error
}
}
else
{
// the subscribe call must occur after the connect callback has completed
client.Subscribe("/example");
}
}
void SubscribeCompleted(object sender, SubscribeCompletedEventArgs e)
{
if (e.Error)
{
// handle error
}
else
{
//success
}
}
void Receive(object sender, ReceiveEventArgs e)
{
// process the receive data
Process(e.Data);
}
Client client = new Client(new ClientArgs
{
RequestUrl = "http://localhost:3010/request.ashx"
});
client.Connect(new ConnectArgs
{
OnSuccess = (successArgs) =>
{
// success
},
OnFailure = (failureArgs) =>
{
// handle connect failure
},
OnStreamFailure = (streamFailureArgs) =>
{
// handle stream failures
}
});
// the subscription can occur at any time, and the WebSync client will wait as needed
client.Subscribe(new SubscribeArgs
{
Channel = "/example",
OnSuccess = (successArgs) =>
{
// success
},
OnFailure = (failureArgs) =>
{
// handle error
},
OnReceive = (receiveArgs) =>
{
// process the received data
Process(receiveArgs.DataJson);
}
});
To upgrade your On-Demand application to WebSync 3, you'll simply need to change your script tags to point to:
<script type="text/javascript" src="http://sync3.frozenmountain.com/client.js"></script>
That will get you going with the latest version of the WebSync JavaScript client. Check out the upgrade information for the JavaScript client here.
The JavaScript client had some internal cleanup, but few breaking API changes. It's simpler to illustrate these changes with some example code, so without further ado, here are the few adjustments you'll need to make to convert to WebSync 3.
The handlerUrl property has been replaced by the requestUrl property, making it consistent with the server naming conventions.
Also, the stream settings are now specified through a sub-object, with a requestUrl property.
The frameUrl property has been removed, and will be determined automatically based on the path to the stream url.
If desired, the old frameUrl value can still be set by the use of the clientFrameUrl property, but generally this is not necessary.
client.initialize({
handlerUrl: 'request.ashx',
streamUrl: 'http://streaming-domain.com/request.ashx',
frameUrl: 'http://streaming-domain.com/client.ashx?frame=1'
});
client.initialize({
requestUrl: 'request.ashx',
stream: {
requestUrl: 'http://streaming-domain.com/request.ashx'
}
});
The url property has been replaced by the requestUrl property, making it consistent with the server naming conventions and with the other client methods.
The onStreamFailure method has been added to simplify handling of failures in the long-held "streaming" connection. If the "willReconnect" flag is set in this method, then it can be considered notification only, as the client will automatically reconnect. If it is not set, then the failure was fatal and needs to be handled.
The "ext" property has been replaced by the "meta" property. This will allow for future user extensions (watch our blog for updates on user extensions in WebSync 3).
Note: The "stream" property of the args passed into the onFailure is no longer valid. Use the onStreamFailure method to detect failures in the streaming connection.
client.connect({
ext: { username: 'foo' },
url: 'request.ashx',
onSuccess: function(args){},
onFailure: function(args){
if(args.stream){
alert('stream failure');
}
}
});
client.connect({
meta: { username: 'foo' },
requestUrl: 'request.ashx',
onSuccess: function(args){},
onFailure: function(args){},
onStreamFailure: function(args){
if(args.willReconnect){ return; }
alert('stream failure');
}
});
The onMetaReceive event has been replaced by the onSubscribersChange event. Note that this event is now available within WebSync Server as well as WebSync On-Demand, provided a reference to the FM.WebSync.Servers.Extensions.Subscribers dll has been added to your project.
A few of the properties in the function callbacks have been updated too, so don't miss those!
client.subscribe({
ext: { username: 'foo' },
channel: '/test',
onSuccess: function(args){
var clientIds = args.data.channels['/test'].clientIds;
},
onFailure: function(args){},
onReceive: function(args){},
onMetaReceive: function(args){
var event = args.data.event;
var clientIds = args.data.clientIds;
}
});
client.subscribe({
meta: { username: 'foo' },
channel: '/test',
onSuccess: function(args){
var clientIds = args.subscribers['/test'];
},
onFailure: function(args){},
onReceive: function(args){},
onSubscribersChange: function(args){
var type = args.change.type; // used to be "event"
var clientIds = args.change.clientIds;
}
});
As with connect and subscribe, the publish method's "ext" property is now the "meta" property:
client.subscribe({
ext: { username: 'foo' },
channel: '/test',
onSuccess: function(args){},
onFailure: function(args){}
});
client.subscribe({
meta: { username: 'foo' },
channel: '/test',
onSuccess: function(args){},
onFailure: function(args){}
});
Note that *all* methods now look for a "requestUrl" property instead of a "url" property when specifying a proxy.
The JavaScript utilities have undergone some cleanup and namespacing to make them more generic, easier to understand, and simpler to use.
| WebSync 2 | WebSync 3 | Description |
|---|---|---|
| fm.utilities.json | fm.json | No longer hidden away, the JSON manipulation methods are now in their own namespace. Check them out here. |
| fm.utilities.xhr | fm.network.xhr | The XHR method has moved into the "network" namespace. This method also no longer accepts multiple arguments, but instead expects a single object literal that names the various parameters explicitly. For details, see the API documentation. |
| fm.utilities.jsonp | fm.network.jsonp | As with the XHR call, the JSON-P method is now moved into the "network" namespace. This method also no longer accepts multiple arguments, but instead expects a single object literal that names the various parameters explicitly. For details, see the API documentation |
The PHP Proxy has remained virtually unchanged, aside from some minor tweaks internally. Thanks to PHP's capability to adjust settings globally for a given script, much of the new capabiliaties in WebSync 3 for the .NET proxy were already possible in PHP. If you have suggestions for how we can improve it, let us know!
Like the .NET Publisher, the PHP Publisher now returns a full object after publishing a message. This object contains information about success or failure of the publication, and if the request failed, any associated error codes. The signature of the Publish call has not changed.
It seems like a lot of changes, but that's only because we've written it out in painful detail to make your life as easy as possible. We want to help; if you have a quick question, just drop us a line and we'll do our best to straighten things out. If you have more in-depth needs, please don't hesitate to pick up a support subscription and contact us to set up a time when we can work through your issues together!