[This post is based on the Windows Azure Tools for Microsoft Visual Studio July 2009 CTP]
That’s right, if you hadn’t guessed what I was working on with my previous posts on .NET Services (Tokens, Queues I, II, III, Routers I & II) I’ve been working towards accessing .NET Services from within a widget. I must apologise for the following as it’s just a code dump of a sample widget that shows how to create a queue and subscribe to an existing router. Note that if you are going to use this on a number of devices you need to create a unique queue on each device, otherwise you’ll end up subscribing to the router multiple times – this will cause duplicate messages in your queue and contention between the devices dequeuing the messages.
To get this widget to work, simply create a widget (Developing Widgets for Windows Mobile 6.5) and then copy the following code into your html file.
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<html http://www.w3.org/1999/xhtml%22″ mce_href=’http://www.w3.org/1999/xhtml”‘>http://www.w3.org/1999/xhtml” >
<head>
<title>Widget Chat</title>
<script type=”text/javascript”>
var theToken;
var theRouter = “myrouter”
var widgetQueue = “widget”;
function connect() {
var solutionName = document.getElementById(“SolutionNameText”);
var solutionPassword = document.getElementById(“SolutionPasswordText”);
alert(‘Solution Name: ‘ + solutionName.value);
alert(‘Solution Password: ‘ + solutionPassword.value);
httpGetAuthenticationToken(solutionName.value, solutionPassword.value, createQueue);
}
function createQueue() {
alert(‘Creating Queue’);
httpCreateQueue(theToken, widgetQueue, subscribeToRouter);
}
function subscribeToRouter() {
alert(‘Subscribing to Router’);
httpSubscribeQueueToRouter(theToken, theRouter, widgetQueue, pollForMessage);
}
function pollForMessage() {
httpDequeueMessage(theToken, widgetQueue, messageReceived, pollForMessage);
}
function messageReceived(message) {
alert(‘Message Received: ‘ + message);
pollForMessage();
}
function send() {
var messageBox = document.getElementById(“Message”);
httpRouteMessage(theToken, theRouter, messageBox.value);
}
function httpGetAuthenticationToken(username, password, callback) {
try {
http = new XMLHttpRequest();
http.open(“GET”, “https://accesscontrol.windows.net/IssueToken.aspx?u=” + username + “&p=” + password);
http.onreadystatechange = function() {
if (http.readyState == 4) {
if (http.status == 200) {
theToken = http.responseText;
alert(‘Authenticated:’ + theToken);
callback();
}
else {
alert(‘Authentication failed’);
}
}
}
http.send();
}
catch (e) {
alert(e.message);
}
}
function httpCreateQueue(token, queue, callback) {
var policy = “<entry mce_href=’http://www.w3.org/2005/Atom”‘>http://www.w3.org/2005/Atom”>” +
“<QueuePolicy mce_href=’http://schemas.microsoft.com/netservices/2009/05/servicebus/connect”‘>“>” +
“<ExpirationInstant>2009-09-03T01:00:00.0000000Z</ExpirationInstant>” +
“</QueuePolicy>” +
“</entry>”;
http = new XMLHttpRequest();
http.open(“POST”, “https://blogsample.servicebus.windows.net/” + queue, false);
http.setRequestHeader(“X-MS-Identity-Token”, token);
http.setRequestHeader(“Content-type”, “application/atom+xml;type=entry;charset=utf-8”);
http.onreadystatechange = function() {
if (http.readyState == 4) {
if (http.status == 201) {
var created = http.responseText;
alert(‘queue created: ‘ + created);
}
else {
alert(‘queue not created – ‘ + http.status);
}
callback();
}
}
http.send(policy);
}
function httpGetServiceList(token) {
http = new XMLHttpRequest();
http.open(“GET”, “https://blogsample.servicebus.windows.net/”, false);
http.setRequestHeader(“X-MS-Identity-Token”, token);
http.onreadystatechange = function() {
if (http.readyState == 4 && http.status == 200) {
output = http.responseText;
alert(output);
// Do something with the service list
httpRenewQueue(token, “mobilequeue”, output);
}
}
http.send();
}
function httpRenewQueue(token, queue, getResponse) {
xmlDoc = new ActiveXObject(“Microsoft.XMLDOM”);
xmlDoc.async = “false”;
xmlDoc.loadXML(getResponse);
var entry;
var entries = xmlDoc.getElementsByTagName(“title”);
var i;
for (i = 0; i < entries.length; i++) {
if (entries[ i ].childNodes[0].nodeValue == queue) {
entry = entries[ i ].parentNode;
}
}
entry.getElementsByTagName(“ExpirationInstant”)[0].childNodes[0].nodeValue = “2009-08-31T09:56:25.2951184Z”;
http = new XMLHttpRequest();
http.open(“PUT”, “https://blogsample.servicebus.windows.net/” + queue + “/!(queue)”, false);
http.setRequestHeader(“X-MS-Identity-Token”, token);
http.setRequestHeader(“Content-type”, “application/atom+xml;type=entry;charset=utf-8”);
http.onreadystatechange = function() {
if (http.readyState == 4 && http.status == 200) {
var output = http.responseText;
alert(‘renew: ‘ + output);
httpEnqueueMessage(token, queue, “Hi Everyone”);
}
}
http.send(entry.xml);
}
function httpDeleteQueue(token, queue) {
http = new XMLHttpRequest();
http.open(“DELETE”, “https://blogsample.servicebus.windows.net/” + queue + “/!(queue)”, false);
http.setRequestHeader(“X-MS-Identity-Token”, token);
http.onreadystatechange = function() {
if (http.readyState == 4 && http.status == 200) {
var deleted = http.responseText;
alert(‘deleted’);
}
}
http.send();
}
function httpEnqueueMessage(token, queue, message) {
http = new XMLHttpRequest();
http.open(“POST”, “https://blogsample.servicebus.windows.net/” + queue, false);
http.setRequestHeader(“X-MS-Identity-Token”, token);
http.setRequestHeader(“Content-type”, “text/plain;charset=utf-8”);
http.onreadystatechange = function() {
if (http.readyState == 4 && http.status == 202) {
var output = http.responseText;
alert(‘enqueue: ‘ + output)
httpDequeueMessage(token, queue);
}
}
http.send(message);
}
function httpDequeueMessage(token, queue, callback, noMessageCallback) {
http = new XMLHttpRequest();
http.open(“DELETE”, “https://blogsample.servicebus.windows.net/” + queue + “/!(queue/head)?encoding=asreply&maxmessages=1&timeout=30”, true);
http.setRequestHeader(“X-MS-Identity-Token”, token);
http.onreadystatechange = function() {
if (http.readyState == 4) {
if (http.status == 200) {
var output = http.responseText;
callback(output);
}
else {
noMessageCallback();
}
}
}
http.send();
}
function httpRouteMessage(token, router, message) {
http = new XMLHttpRequest();
http.open(“POST”, “https://blogsample.servicebus.windows.net/” + router, false);
http.setRequestHeader(“X-MS-Identity-Token”, token);
http.setRequestHeader(“Content-type”, “text/plain;charset=utf-8”);
http.onreadystatechange = function() {
if (http.readyState == 4) {
if (http.status == 202) {
var output = http.responseText;
alert(‘Send ok!’);
}
else {
alert(‘Unable to send’);
}
}
}
http.send(message);
}
function httpSubscribeQueueToRouter(token, router, queue, callback) {
var policy = “<entry mce_href=’http://www.w3.org/2005/Atom”‘>http://www.w3.org/2005/Atom”>” +
“<link rel=’alternate’ href=’https://blogsample.servicebus.windows.net/” + queue + “‘ />” +
“<HttpHeaders mce_href=’http://schemas.microsoft.com/netservices/2009/05/servicebus/connect”‘>“>” +
“<HttpHeader name=’X-MS-Identity-Token’ value='” + token + “‘ />” +
“</HttpHeaders>” +
“</entry>”;
http = new XMLHttpRequest();
http.open(“POST”, “https://blogsample.servicebus.windows.net/” + router + “/!(router/subscriptions)”, false);
http.setRequestHeader(“X-MS-Identity-Token”, token);
http.setRequestHeader(“Content-type”, “application/atom+xml;type=entry;charset=utf-8”);
http.onreadystatechange = function() {
if (http.readyState == 4) {
if (http.status == 200) {
var created = http.responseText;
alert(‘subscribed ok:’ + created);
callback();
}
else {
alert(‘not subscribed ok’ + http.status);
}
}
}
http.send(policy);
}
</script>
</head>
<body>
<p>
Solution Name:<br />
<input id=”SolutionNameText” type=”text” />
<br />
Solution Password:<br />
<input id=”SolutionPasswordText” type=”password” /><br />
<Button onclick=”connect()”>Connect</Button>
</p>
<p>
Message:
<br />
<input id=”Message” type=”text” /><br />
<Button onclick=”send()”>Send</Button>
</p>
</body>
</html>