After introducing the topic – as well as creating our basic, local web-service – in the last post, today we’re going to publish our MVC 4 Web API application to the cloud and see it working from a number of different client environments.
Preparing to publish to Azure
Now that we’re ready to publish to Azure, we need to add a deployment project to our solution. Right-click “ApollonianPackingWebApi” in the Solution Explorer and select “Add Windows Azure Cloud Service Project”. This will add a new project into our solution.
We can now double-click the entry under the “Roles” folder in order to adjust the parameters for that role.
It’s here that we can adjust the number and of size of the instances to deploy to Azure, as well as more advanced settings related to Virtual Networks and Caching.
Then we can right-click on the newly added project and select “Publish…”.
We need to sign in to MSDN in order to get our credentials – these get downloaded to your local system in a .publish file – and after selecting “Next” we can add a new cloud service in our preferred location, as well as choosing whether to post to staging or production (we’ll be lazy and go straight to production) and specifying remote desktop settings in case we want to connect to the VM instance hosting our role (sometimes needed in case of debugging).
The actual deployment process can take some time (~5 minutes or so), at which point we should see a “completed” message inside Visual Studio:
Now the site will be ready for testing at the URL you assigned to your cloud service, e.g.:
http://apollonian2.cloudapp.net
And, of course, the web-services, too:
http://apollonian2.cloudapp.net/api/circles/2/2
http://apollonian2.cloudapp.net/api/spheres/2/2
So that’s all there is to it – we now have a functioning, cloud-based web-site and -service.
To get information on the web-service’s status – including its usage, cost & billing information – you can log into the Windows Azure Management Console:
Calling our web-service from anywhere*
* AutoCAD, Android, iOS, WinRT, HTML5 & Unity3D.
In this section, we’ll take a whirlwind tour of some different client environments.
Let’s start by revisiting AutoCAD, looking at some C# code that calls into our web-service rather than the local F# code.
At the core of this implementation we need some HTTP-related code to call the web-service and some JSON-related to code to parse the results.
Here’s the function we’ll use to call the web-service:
private static dynamic ApollonianPackingWs(
Editor ed, double p, int numSteps, bool circles
)
{
string json = null;
// Call our web-service synchronously (this isn't ideal, as
// it blocks the UI thread)
HttpWebRequest request =
WebRequest.Create(
"http://apollonian.cloudapp.net/api/" +
(circles ? "circles" : "spheres") +
"/" + p.ToString() +
"/" + numSteps.ToString()
) as HttpWebRequest;
// Get the response
try
{
using (
HttpWebResponse response =
request.GetResponse() as HttpWebResponse
)
{
// Get the response stream
StreamReader reader =
new StreamReader(response.GetResponseStream());
// Extract our JSON results
json = reader.ReadToEnd();
}
}
catch (System.Exception ex)
{
ed.WriteMessage(
"\nCannot access web-service: {0}", ex.Message
);
}
if (!String.IsNullOrEmpty(json))
{
// Use our dynamic JSON converter to populate/return
// our list of results
var serializer = new JavaScriptSerializer();
serializer.RegisterConverters(
new[] { new DynamicJsonConverter() }
);
// We need to make sure we have enough space for our JSON,
// as the default limit may well be exceeded
serializer.MaxJsonLength = 50000000;
return serializer.Deserialize(json, typeof(List<object>));
}
return null;
}
There’s really not a great deal to it, although there’s a little work going on to deserialize the JSON returned. If we were targeting .NET 4.5 rather than 4.0, we could make use of some new capabilities in the .NET Framework to parse JSON, but this version makes use of a 3rd party JSON serializer (from here). One thing I liked about this particular implementation was its use of .NET 4.0’s dynamic keyword to simplify parsing the JSON. This capability has apparently now been added to the Json.NET library, so if I was starting again I might possibly choose that, instead (I’ve used it successfully on other projects calling web-services).
Our main implementation – excluding the code requesting data from the user – now becomes:
Transaction tr =
doc.TransactionManager.StartTransaction();
using (tr)
{
// Start by creating layers for each step/level
Utils.CreateLayers(db, tr);
// We created our Apollonian gasket in the current space,
// for our 3D version we'll make sure it's in modelspace
BlockTable bt =
(BlockTable)tr.GetObject(
db.BlockTableId, OpenMode.ForRead
);
BlockTableRecord btr =
(BlockTableRecord)tr.GetObject(
bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite
);
// Let's time the WS operation
Stopwatch sw = Stopwatch.StartNew();
dynamic res = ApollonianPackingWs(ed, radius, steps, false);
sw.Stop();
if (res == null)
return;
ed.WriteMessage(
"\nWeb service call took {0} seconds.",
sw.Elapsed.TotalSeconds
);
// Go through our "dynamic" list, accessing each property
// dynamically
foreach (dynamic tup in res)
{
double rad = System.Math.Abs((double)tup.R);
if (rad > 0.0)
{
Solid3d s = new Solid3d();
s.CreateSphere(rad);
Point3d cen =
new Point3d(
(double)tup.X, (double)tup.Y, (double)tup.Z
);
Vector3d disp = cen - Point3d.Origin;
s.TransformBy(Matrix3d.Displacement(disp + offset));
// The Layer (and therefore the colour) will be based
// on the "level" of each sphere
s.Layer = tup.L.ToString();
btr.AppendEntity(s);
tr.AddNewlyCreatedDBObject(s, true);
}
}
tr.Commit();
ed.WriteMessage(
"\nCreated {0} spheres.", res.Count
);
}
As you’d expect, the code works in a very similar fashion to the previous implementation (it’s the same code doing the work, just in a geographically different location :-).
Supporting multiple platforms
We’ll now take a look at some options for creating viewers of our 3D data on different platforms.
We’ll start by looking at some native clients for Android, iOS and Windows 8, before looking at one cross-platform toolkit (Unity3D) and then HTML5 (via WebGL).
If you’re interested in continuing the discussion, there’s a conveniently timed round-table session following on after this session (hosted by myself and Philippe Leefsma from the ADN team):
Apollonian Viewer for Android
The Android stack is Java-based, which made it a very familiar environment (at least with respect to the code created) for a C# developer such as myself. The tooling was a bit different – the IDE I used was Eclipse – but I was surprised to find out how much I ended up enjoying it: there are a few quirks, but there are also capabilities I’d really like to see in Visual Studio, such as warnings regarding unused namespaces.
The 3D object library – to avoid making low-level calls into OpenGL ES 2.0 – was named Rajawali. An open source toolkit developed by Dennis Ippel in the UK, who provided me with some great support (and even custom features) during the implementation. And the results were very impressive.
Apollonian Viewer for iOS
Now I fully admit I have trouble with Objective-C. I understand its syntax is dictated largely by its origins (it was apparently inspired by Smalltalk, back in the day), but I have become so very used to a traditional structure for calling methods (object.method(arg1,arg2)) that I find Objective-C very difficult to adjust to.
That said, it does appear to be a very powerful, capable and well-loved language. It’s just not something In enjoyed working with closely, myself.
The development environment was Xcode, which I found to be convoluted and unstable, but I assume this is something you get used to.
The 3D object library was iSGL3D – I also looked into a few others but found this to be the best fit, overall. Once again it was based on OpenGL ES 2.0, but the similarities to Rajawali ended there: I found it difficult to get good results (perhaps because I didn’t have direct help from the developer and struggled with Objective-C, in general).
Apollonian Viewer for WinRT
Developing a WinRT-focused client – one that works a Windows Store application on Windows 8 – was interesting. I had already done some work on WinRT, but writing a 3D viewer meant diving into DirectX. In theory you’re supposed to call this from C++ but I ended up wimping out and making use of SharpDX to bridge to it from C#.
Development was done in VS2012 (which was just fine), but because – at least at the time of writing – I couldn’t find a decent 3D object library, I had to get down and dirty and write my own pixel and vertex shaders. A pretty painful experience – I had to learn a great deal about rendering pipelines that I’ve since forgotten – but the results were pretty impressive.
Apollonian Viewer for HTML5
In order to understand the possibilities around HTML5 – which many people believe to be the future for cross-platform development – I decided to dive in and create a WebGL-based viewer for our data.
HTML5 means JavaScript – which I like better than Objective-C, although it’s far from being my favorite language – but I did find the tools available to me had evolved considerably since I last used it in earnest: modern browsers have pretty advance debugging capabilities and even Visual Studio does a pretty good job with the language.
I chose Three.js as the 3D object library, and found it excellent: the results were impressive. It worked well from most browsers – although had to fall back to “canvas” rendering in IE, which was a shame. WebGL is hardware accelerated, so the performance was great.
Viewing an apollonian packing in a Unity scene
And finally, let’s take a look at Unity, a popular, cross-platform game engine that's increasingly used for visualization. I had really wanted to try out this toolkit: I’d heard great things about from a number of people and also felt it wouldn’t be fair to only focus on native apps and HTML5 without taking a look at it.
I haven’t written the title of this section as if I had written a new viewer, although some people have used Unity to do just this: I merely wanted to make use of a standard Unity scene and add the results of our web-service call into it.
I used Unity on OS X (and also had a play with the Windows version) and was able to target a number of environments for free (desktop environments and the web). You can pay to be able to target additional platforms – the list is impressive.
From a programming perspective it was easy: I used C# – Unity uses Mono to make this work when not on Windows – but might also have chosen JavaScript. The development environment – when I needed to work on code outside the Unity scene editor – was MonoDevelop: a fairly decent IDE.
Summary
To summarize what we’ve seen in this session…
- We extracted some F# code from an existing AutoCAD application
- We placed it behind a web-service implemented using ASP.NET MVC4
- We published the web-service to Windows Azure
- We then modified the AutoCAD client to call the web-service
- We then saw how we could also use the data from…
- Native apps: Android, iOS, WinRT
- Web apps: HTML5 & WebGL
- Cross-platform apps: Unity
Overall the experience of creating the web-service was straightforward, although admittedly we kept things really simple: if we’d chosen to implement authentication life would have been at least marginally more interesting. Posting to Azure and managing the deployment was also made very easy by the integrated and standalone tools.
It was fun to do some native development, to understand what’s involved (although I enjoyed Android, WinRT and iOS in that order, I would say). On balance, though, I expect HTML5 to come into its own – even on mobile devices – over the coming year, and if you need to support multiple platforms it’s well worth investigating the cross-platform tools that meet your requirements.
Want to continue the discussion? Come along to the round-table in 30 minutes time!
If you’d like to take a look at the various projects related to this session, you can find them here (30.7 MB).
Blog References
Circle packing in AutoCAD: creating an Apollonian gasket using F# – Part 1
Circle packing in AutoCAD: creating an Apollonian gasket using F# – Part 2
Sphere packing in AutoCAD: creating an Apollonian packing using F# – Part 1
Sphere packing in AutoCAD: creating an Apollonian packing using F# – Part 2
Exposing a RESTful web service for use inside AutoCAD using the ASP.NET Web API – Part 1
Exposing a RESTful web service for use inside AutoCAD using the ASP.NET Web API – Part 2
Consuming data from a RESTful web-service inside AutoCAD using .NET
Hosting our ASP.NET Web API project on Windows Azure – Part 1
Hosting our ASP.NET Web API project on Windows Azure – Part 2
Using Windows Azure Caching with our ASP.NET Web API project
Calling a cloud-based web-service from AutoCAD using .NET
Calling a web-service from a Unity3D scene
Creating a 3D viewer for our Apollonian service using Android – Part 1
Creating a 3D viewer for our Apollonian service using Android – Part 2
Creating a 3D viewer for our Apollonian service using Android – Part 3
Creating a 3D viewer for our Apollonian service using iOS – Part 1
Creating a 3D viewer for our Apollonian service using iOS – Part 2
Creating a 3D viewer for our Apollonian service using iOS – Part 3
Creating a 3D viewer for our Apollonian service using HTML5 – Part 1
Creating a 3D viewer for our Apollonian service using HTML5 – Part 2
Creating a 3D viewer for our Apollonian service using HTML5 – Part 3
Creating a 3D viewer for our Apollonian service using WinRT – Part 1
Creating a 3D viewer for our Apollonian service using WinRT – Part 2