Vault on Metro

Update:  I've just been informed that Microsoft stopped using the word using the term Metro.  The current term is "Windows Store Apps" or something like that. 

Last December, my Christmas present to myself was a Windows Surface tablet.  In typical me-style, I decided to write an app for it.  Overall, it was a pain getting the app to work.  I expected it to be easy to write a Microsoft tablet app using Microsoft Visual Studio and the Vault API, which is built on Microsoft .NET.  Alas, no, it was a pain to get the app working. 

Requirements:

  • Visual Studio 2012
  • Windows 8
  • Vault 2014

Click here for the source code
Compiled app not available


The app itself is a simple folder browser.  Nothing fancy.  I just wanted to figure out the steps for getting the Vault API to work.  I basically took the “Grid App” template project from VS and modified it to work with Vault. Let me take you through the app…

None of the Vault SDK libraries work

The Connection object, the WebServiceManager, IExplorerUtils, none of those work for a Metro app.  The Vault SDK DLLs require .NET libraries not present in Metro.  If you want the Vault objects, you will have to go “old school” and set of the service references directly. 

It’s always annoying going from a full set of libraries (Winforms/XAML) to a subset of libraries (Metro).  I understand why this is needed, but it baffles me why some things are left out.  Android has a reduced set of Java libraries, but it doesn’t feel that way when you are programming with it.  In a perfect world, Metro would be that way too.

Anyway, to set up your Vault service objects (DocumentService, AuthService, etc), you need to add Service References in your VS project.  You do this by right-clicking on your project and selecting Add Service Reference.

First, you need to insert the address of the web service.  In Vault 2014, there are 2 main locations for web services.  Filestore services are located at
http://[serverName]/autodeskdm/services/filestore/v18/[serviceName].svc.  And all other web services are at
http://[serverName]/autodeskdm/services/v18/%5BserviceName%5D.svc .

If everything goes well, clicking Go should show you a list of functions for that service.  Before you click OK, make sure you set the namespace to something useful.  You are going to have multiple services for any given Vault app, so the namespace needs to be clear.

To log in you will need the AuthService, which is in the filestore URL path.


The SecurityHeader

VS generated the SecurityHeader class, but it didn’t hook it up to anything.  The SecurityHeader is pretty important.  It contains your user’s session information.  Vault requires this information on almost every web service call.  That’s how Vault knows that who you are so that it can apply permissions.  If you can’t send the SecurityHeader, you can’t use the Vault API.  Period.

If you set a Service Reference in a normal VS project, the SecurityHeader is hooked up for you automatically.  I have no idea why a Metro app is different.  I had to spend most of my time, searching around on how to manually read/write header data on your web service calls.

 

Step 1:  Set the [XMLRoot] attribute
When you set up a Service Reference, Visual Studio auto-generates a bunch of files.  Go into the Reference.cs file for your AuthService.  You will need to “Show All Files” if you want to see it in your VS project.  Find the SecurityHeader class and replace the [System.Xml.Serialization.XmlTypeAttribute] attribute with this:

[System.Xml.Serialization.XmlRoot(Namespace=http://AutodeskDM/Services)]

Since this is an auto-generated file, you need to be on the lookout.  Actions in VS, like changing the project settings, may trigger an update of this file, which overwrites the change.

 

Step 2:  Logging in
When you call the Login function, you don’t get back a direct result.  However, there is a SecurityHeader object in the header XML.  You have to go through through some hoops in order to read that header in a Metro app.  Actually, I had to go through the hoops; you can just copy my code.

using System.ServiceModel;

using System.ServiceModel.Channels; 

public void Login(string server, string vault, string username, string password)

{

    // sign into Vault and remember the security header 

    using (OperationContextScope scope = new OperationContextScope(authClient.InnerChannel))

    {

        OperationContext current = OperationContext.Current;

 

        authClient.SignInAsync(server, vault, username, password).Wait();

        HttpResponseMessageProperty httpResponseProperty = new HttpResponseMessageProperty();

 

        XmlDictionaryReader dict = current.IncomingMessageHeaders.GetReaderAtHeader(0);

        string securityStr = dict.ReadOuterXml();

        XmlSerializer serializer = new XmlSerializer(typeof(AuthSvc.SecurityHeader));

        System.IO.StringReader reader = new System.IO.StringReader(securityStr);

        securityHeader = serializer.Deserialize(reader) as AuthSvc.SecurityHeader;

    }

}

Save that securityHeader object. You will need it for all other Vault calls.

 

Step 3: Using the header

Now that we are logged in, we can actually start reading/writing Vault data.  On every call we need to set the securityHeader.  It’s basically the same steps from part 2 but in reverse.

In my sample, I wrap all the calls in a delegate. 

private T DoWebServiceCall<T>(Func<T> a)

{

    using (OperationContextScope scope = new OperationContextScope(docClient.InnerChannel))

    {

        // set the security header and make the web service call 

        OperationContext current = OperationContext.Current;

        MessageHeader header = MessageHeader.CreateHeader("SecurityHeader", "http://AutodeskDM/Services&quot;, securityHeader);

        current.OutgoingMessageHeaders.Add(header);

 

        return a();

    }

}

public DocumentSvc.Folder GetFolderById(long folderId)

{

    return DoWebServiceCall(delegate

    {

        return docClient.GetFolderByIdAsync(folderId).Result;

    });

}


Conclusion:

That’s it for now.  I used up all my time figuring out the security header stuff, so the app itself isn’t much to speak of.  I left out a bunch of things like multi-threading, logging out of Vault, error handling, cashing and useful functionality.  I’ll leave it to you to figure all of those things out if you want to write a Metro app.


Comments

One response to “Vault on Metro”

  1. nice work… I wonder how any of the dwf’s could be viewed.

Leave a Reply to scott moyseCancel reply

Discover more from Autodesk Developer Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading