By now you might have some experience using App Orchestration. However I doubt many of you have dug down into the API that runs everything behind the scenes. We provide a very nice front end UI, but as we all know no UI does all the things you might want it to do, or in the special way you want to do it. What I am going to show you is how to do that custom part, or at least get started. I will also show you 4 different ways to do the same thing. The web has a whole lot of different ways to do things, and we have designed this API to be as compatible as possible with those techs by making it a standard REST API so no matter what or how you like to develop, we should have you covered.

I will show you how to enumerate the offerings provided (A very common task. This is the heart of the Hosted Apps and Desktop Service used by CPSM.) in these ways:

  1. Via Webforms (Part 1)
  2. Via Razor using an MVC model. (Part 2)
  3. Via knockout JS and ajax. (Part 3)
  4. Via Angular JS. (Part 4)

I’ve started off with the old school webforms using the default solution produced by Visual Studio 2012. It comes with a login mechanism already built in, so I leveraged that to hook in the App Orchestration client authentication. The excerpts below are from the upcoming new version of the API. You can do this today with the released v1 API , but the syntax will be a bit different.

Here is a picture of what we will build:

The first part is the login code:

    protected void OnLoggedIn(object sender, EventArgs e)
        // Encrypt password
        var securePass = new SecureString();
        foreach (var c in LoginControl.Password)

        string userName = LoginControl.UserName;

        // Create the API Context
        Session["ApiContext"] = new ExplicitAuthContext(DefaultApiServiceAddress, userName, securePass);

The OnLoggedIn event is handled for the login control and the user name and password are then used to create a new ApiContext that talks to the App Orchestration Configuration service. Once that completes, the API is ready to use through out your code.

The offerings are loaded on the default page via a repeater: (And yes, I used a table, but this is a table of offerings. I stripped out some of the other columns normally used for simplicity. So please don’t shoot me. 🙂

<asp:Content runat="server" ID="BodyContent" ContentPlaceHolderID="MainContent">
    <asp:Repeater runat="server" ID="rptOfferings" OnItemDataBound="ItemDataBound">
                <table width="100%" border="0" cellpadding="5" cellspacing="0" id="tblOfferings">
                        <th style="text-align: left; width: 5%">Offering</th>
                        <th style="text-align: left; width: 95%"></th>

                <tr class="tabletext2Alt" id="trd" runat="server">
                        <asp:Image id="offeringIcon" runat="server" style="margin-left:5px;" />
                    <td valign="top">
                        <asp:Label runat="server" id="lblOfferingName" style="vertical-align:middle; text-align: left;" CssClass="Heading3" Text='<%#DataBinder.Eval(Container.DataItem, "Name")%>' />

The magic happens on the back end where the Offering Data is bound to the repeater. The Icon URL is then also filled by an ItemDataBound handler that loops through each item of the repeater. The actual Icon loads in later via an HttpHandler as a separate URL request handled via the browser.
    protected void BindData()
        if (ApiContext == null) return;
        var offerings = ApiContext.Offerings.Get();
        rptOfferings.DataSource = offerings;

    protected void ItemDataBound(object sender, RepeaterItemEventArgs e)
        var offering = e.Item.DataItem as Citrix.Cam.Configuration.Api.Models.OfferingModel;
        var icon = e.Item.FindControl("offeringIcon") as Image;

        if (icon != null && offering != null)
            icon.ImageUrl = String.Format("imagehandler.ashx?IconId={0}", offering.Icon.Id);

That is about all you need to produce the above screenshot. Not too bad was it? And that was using WebForms! In the next parts we see this get easier, well all least a little more coherent with some more modern technologies used.

Stay tuned!