Here is the first post of a series that aims at dissecting the various aspects and technologies that can be used in order to create a cloud based viewer for models extracted from some of the major Autodesk desktop applications, namely Inventor, AutoCAD and Revit.
The diagram below illustrates the general concept:
Some explanations about it: The desktop computer on the top left corner is running one of the mentioned above desktop application plus a custom add-in that acts like a management console, allowing users to upload models to a cloud based service or delete existing models hosted on the cloud.
The models are meshed on the console side, then the data is uploaded through a WCF web service to a cloud hosted server. Through the use of Amazon technology, the model data is stored onto the cloud and information relative to which models are hosted is kept in a database, so it can be retrieved without having to examine the model data itself. A series a client viewer applications will be implemented, allowing to visualize the 3d models on various platforms: desktop computers, Android and iOS devices, and Web browsers supporting WebGL technology.
This first post illustrates how to create the two first components of our cloud viewer, which are the WCF service and for testing a desktop executable that consumes that service. In this series I want to demonstrate how to put in place a framework rather than showing in details the complexity of the actual viewer. For that reason I chose to focus on a simplified version of the viewer. Instead of uploading Autodesk models, our viewer will work with image files (jpg, png, bmp). The complete implementation of the viewer will be provided at a later time (around December 2012 timeframe), as it is still a work in progress at the moment.
I – Creating a WCF Service
First we need to create a new project, I use C# as it is my favorite programming language. Select the “WCF Service Application”, as we want to host our service in IIS. I name it “AdnCloudViewerService”:
I also create a Winform Standalone Executable application that will be used as client to test the service once it’s running.
After a bit of renaming my project architecture looks as follow:
The implementation for my “AdnCloudViewerSrv” service is at the moment a dummy one: it will return an hardcoded array of “ModelInfo” elements.
Here is the declaration of my interface and data structure:
namespace AdnCloudViewerService
{
[ServiceContract]
public interface IAdnCloudViewerSrv
{
[OperationContract]
ModelInfo[] GetDbModelInfo();
}
[DataContract]
public class ModelInfo
{
public ModelInfo(int height, int width, string ext, string id)
{
Height = height;
Width = width;
FileExt = ext;
ModelId = id;
}
[DataMember]
public int Height
{
get;
private set;
}
[DataMember]
public int Width
{
get;
private set;
}
[DataMember]
public string FileExt
{
get;
private set;
}
[DataMember]
public string ModelId
{
get;
private set;
}
}
}
You can notice the presence of WCF specific attributes “ServiceContract”, “OperationContract”, “DataContract” and “DataMember”.
-
The ServiceContract contains the methods you want to expose for a service, using the OperationContract will expose that method to the service clients. The custom data structures used by the service must also be exposed using the DataContract / DataMember attributes. For the actual implementation of “AdnCloudViewerSrv”, I let you refer to the attached sample.
-
We now need to run our web service. In that first post, we are just going to host it locally. There are several options to host a WCF service:
- Hosting the service in a standalone .Net executable (this is done through the “ServiceHost” functionality)
- Hosting in a windows service
- Hosting in IIS 7.0
The most flexible and easiest method is probably using IIS, as it doesn’t require any extra coding at the moment. So we will go ahead and use IIS.
-
II – Hosting WCF Service in IIS
-
The Visual Studio project template generate for us a default web.config file that will work straight away if we host the service in IIS, so at the moment we don’t need to modify it at all. We will do it in later posts in order to add endpoints to our service and use different protocols.
-
This default config file looks as follow. Notice the presence of the “<serviceMetadata httpGetEnabled="true"/>” tag that enables our service to expose its metadata:
-
-
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information,
set the value below to false and remove the
metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for
debugging purposes, set the value below to true.
Set to false before deployment to avoid
disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
We now need to build a deployment package for easy deployment on IIS. Let’s create a publish settings for that. Go to that little control, it should be somewhere in the Visual Studio toolbars, then select <New…>:
-
Select the “Web Deploy Package” method and fill up the location and site fields. I name my application with a fancy name: “AdnCloudViewer”:
-
Then “Publish” the package. If the build is successful it should produce a zip file that can easily be deployed in IIS.
Now fire IIS management console and go to “Default Web Site” > “Deploy” > “Import Application…”
You need to have Web Deploy installed on the machine for that option to be available.
Browse to your zipped package and accept all the default settings, you should see the following dialog at the end:
Fire a web browser and go to the address:
http://localhost:80/AdnCloudViewer/AdnCloudViewerSrv.svc, if you see something like the following, bingo! our web service is up and running… locally.
III – Creating a desktop client application
Let’s now consume our web service by creating a simple desktop .Net client.
I create a winform that looks like below in order to be able to list the various models we have hosted on the cloud, in a left side TreeView control, a PropertyGrid to display the various fields and a PictureBox for the later versions to display the images:
First thing is to reference our service, so go the “Add Service Reference…” from the right-click menu and input the address of our running service, you should get the following result if the service can be reached:
Customize the “Namespace” field to whatever you want, and select the “Advanced…” option that brings a second dialog. There make sure you tick the “Generate asynchronous operations” box, this saves us a lot of work in order to be able to perform asynchronous calls to our service:
The code to connect to our service is very straightforward, we have a unique endpoint at the moment, so a single line is requested:
bool ConnectService()
{
try
{
_viewerClient = new AdnCloudViewerSrvClient();
return true;
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message);
return false;
}
}
From our “AdnCloudViewerSrvClient” we could now simply call the “GetDbModelInfo” and place a break point to see that our service is working as expected:
However invoking that method directly result in a synchronous call. Most of the time you will want to perform asynchronous call to a web service, due to the latency the UI will look frozen otherwise.
The following code illustrates how to achieve the asynchronous call, it is slightly more complex, but the asynchronous wrappers have already been generated by Visual Studio:
private void BeginRefreshCloudModels()
{
_tvModels.Nodes.Clear();
TreeNode root = _tvModels.Nodes.Add(
"_cloudModelsKey", "Cloud Models", 0, 0);
_viewerClient.BeginGetDbModelInfo(
new AsyncCallback(GetDbModelInfoAsyncResponder),
null);
}
private void EndRefreshCloudModels(ModelInfo[] infos)
{
TreeNode root = _tvModels.Nodes[0];
foreach (ModelInfo info in infos)
{
TreeNode node = root.Nodes.Add(info.ModelId);
node.Tag = info;
}
root.Expand();
}
private delegate void RefreshCloudModelsDelegate(ModelInfo[] infos);
private void GetDbModelInfoAsyncResponder(IAsyncResult result)
{
try
{
ModelInfo[] infos = _viewerClient.EndGetDbModelInfo(result);
if (result.IsCompleted)
{
this.Invoke(
new RefreshCloudModelsDelegate(EndRefreshCloudModels),
new object[] { infos });
}
}
catch (Exception ex)
{
}
}
With that we can finish the implementation of our desktop viewer and test it:
That’s it for today folks. In the next post we will take a look at two Amazon APIs SimpleDb and S3, and add further functionalities to our web service in order to upload actual images and retrieve them from the client…
Comments
You can follow this conversation by subscribing to the comment feed for this post.