System Center Orchestrator Custom Interface – C# / ASP.NET


Welcome to another System Center PFE blog post. In this publication I will continue to highlight how the System Center Suite of products can help manage and automate complex processes. If you’ve read my first post in this series, you will recall that the process being detailed is the graceful application of updates to a multi-node SQL cluster. I will continue to use this scenario as the subject process for this blog; however, make no mistake, this series of posts is not about updating SQL clusters, but rather an introduction to the features of System Center and process automation. The goal of this article series is to show the potential of ‘IT as a Service’ while using complex real world use cases as the example subject matter.

 

Goals for this blog:

  • Quick discussion about Orchestrator Interfaces.
  • Demonstrate the creation and use of a C#/ASP.NET External Interface that will pass Initialization data to our SQL Cluster Updating Runbook and start the Runbook.

 

Scenario / Use Case:

As a member of the Contoso IT staff managing System Center and Automation, you have completed development on a series of cluster updating Orchestrator Runbooks, which have successfully automated the cluster updating process. While the native System Center Orchestrator 2012 Orchestration Console provides the necessary interfaces from which to pass initialization data and start the updating process, management has asked for a custom interface that can be integrated into the already existing Contoso IT portal. Your task is to develop a custom System Center Orchestrator web interface which will interact with the Orchestrator Web Service allowing Contoso staff to pass initialization data and start the Cluster Updating process.

 

Interfaces:

When speaking of interfaces, we are referring to any programmatic method by which to interact with the Orchestrator Web Service or Runbook Server. Through these interfaces we can pass initialization data to our Runbooks, start and stop a Runbook, and retrieve data about Runbooks.

Native Interfaces – Out of the box we have the Runbook Designer, Runbook Tester, and the Orchestration Console. Each of these has a target use case, with the Orchestration console being most suitable as a ‘published interface’. In my last blog post I demonstrated use of the Orchestration Console. While the Orchestration Console can perform all interface requirements, it may not suit all situations, such as the scenario detailed in this publication. What are the alternatives?

Orchestrator Web Service – Orchestrator will ship with a REST-based web service providing a surface from which to interface with Orchestrator Runbooks. Basically we can interface with Orchestrator using any programmatic method that is capable of interacting with a REST-based web service (PowerShell, .NET, VBSCRIPT, Etc.). This is the interfacing method we will be examining in this article.

System Center Service Manager 2012 – while Service Manage will also use the Orchestrator Web Service as the interface mechanism, Orchestrator and Service Manager are so tightly integrated and powerful when coupled that I’ve decided Service Manager is worthy of a bullet point in its own right. In my opinion this is the true nirvana of Orchestrator Interfaces. Stay tuned, I will be examining the marriage of System Center Service Manager 2012 and System Center Orchestrator 2012 in future article posting.

 

Creating the custom interface:

With an understanding of what an interface is, let’s explore the creation of our own. Before getting started, here are a few resources I used as reference material when developing this solution.

Robert Hearn – Fun with the Orchestrator Beta Web Service and Powershell

Damian Flynn – Orchestrator, C#, and Runbooks

Assumptions – The assumption here is that we have an Orchestrator Runbook solution tested, in place, and ready for consumption.  Additionally we need to verify that the Orchestrator Web Service is functioning. To do so browse to HTTP://<SERVERNAME>:81/Orchestrator2012/Orchestrator.svc – this should produce a page containing XML. If it does you should be ready to start the exercise.

Step 1:  Custom Class File -Before starting our project in Visual Studio, we need to generate a custom class file containing the client data service classes that our .NET application can utilize to access the web service. This is quite easy. Open up a command prompt (I’ve done this on the Orchestrator box but I do not believe this is necessary), navigate to the following folder ‘%windir%\Microsoft.NET\Framework\v3.5’, and run the following command

DataSvcUtil.exe /dataservicecollection /version:2.0 /language:CSharp /out:desiredfilename.cs /uri: HTTP://<SERVERNAME>:81/Orchestrator2012/Orchestrator.svc

The output will look similar to the following and the .CS file can be found in the folder from which DataSvcUtil.exe was executed.


More information on how to use DataSvcUtil.exe can be found here – http://msdn.microsoft.com/en-us/library/ee383989.aspx

 Step 2:  Design Our Web Application – For the sake of this demonstration this application will be very simple. A few text boxes and a submit button. I will not go into the details of creating this form.

 

Step 3: Setting up the .NET Environment – Once the form design has been completed, we will need to set up the .NET environment. From within the Visual Studio designer, double click on the ‘Update’ button in order to bring up the code editor with focus on the Default.aspx.cs file (if this file has not been renamed).

  • Add using System.Xml.Ling; to the using statements.
  • Add the .CS File created in step 1 to the project – right click on the project in solution explorer, add existing item, select the .CS file.
  • Add a reference right click on References, Add Reference, select .NET, and select System.Data.Services.Client.

When finished you will see the following three items boxed in red.

 

 Step 4: Begin Coding – For the sake of this blog post size, I will just paste the code here and give a quick description of the relevant lines.

 

Code Snippet
  1. protected void Button1_Click(object sender, EventArgs e)
  2.       {
  3.  
  4.          string strServer = txtServer.Text;
  5.          string strEmail = txtEmail.Text;
  6.          string strCluster;
  7.  
  8.          if (chkCluster.Checked)
  9.             strCluster = “True”;
  10.          else
  11.             strCluster = “False”;
  12.                         
  13.          var scorchSVC = new Microsoft.SystemCenter.Orchestrator.WebService.OrchestratorContext(new Uri(@”http://twosys2012scorc:81/orchestrator2012/orchestrator.svc”));
  14.          scorchSVC.Credentials = new System.Net.NetworkCredential(“username”, “password”, “domain”);
  15.  
  16.          var runbooks = (from rbData in scorchSVC.Runbooks
  17.                          where rbData.Name == “1.0 – Cluster Updates”
  18.                          select rbData).ToList();
  19.  
  20.          var runbookpars = (from rbData in scorchSVC.RunbookParameters
  21.                             where rbData.RunbookId == runbooks.Single().Id
  22.                             select rbData).ToList();
  23.  
  24.          var input1param = (from rbData in runbookpars
  25.                             where rbData.Name == “Server”
  26.                             select rbData).Single();
  27.  
  28.          var input2param = (from rbData in runbookpars
  29.                             where rbData.Name == “Email”
  30.                             select rbData).Single();
  31.  
  32.          var input3param = (from rbData in runbookpars
  33.                             where rbData.Name == “Cluster”
  34.                             select rbData).Single();
  35.  
  36.          var paramxml = new XDocument(
  37.                         new XElement(“Data”,
  38.                            new XElement(“Parameter”,
  39.                               new XElement(“Name”, input1param.Name),
  40.                               new XElement(“ID”, input1param.Id.ToString(“B”)),
  41.                               new XElement(“Value”, strServer)
  42.                                     ),
  43.                             new XElement(“Parameter”,
  44.                               new XElement(“Name”, input2param.Name),
  45.                               new XElement(“ID”, input2param.Id.ToString(“B”)),
  46.                               new XElement(“Value”, strEmail)
  47.                                     ),
  48.                             new XElement(“Parameter”,
  49.                               new XElement(“Name”, input3param.Name),
  50.                               new XElement(“ID”, input3param.Id.ToString(“B”)),
  51.                               new XElement(“Value”, strCluster)
  52.                                     )));
  53.  
  54.          var job = Microsoft.SystemCenter.Orchestrator.WebService.Job.CreateJob(System.Guid.NewGuid(), runbooks.Single().Id, “user1”, DateTime.Now, “user1”, DateTime.Now);
  55.  
  56.          string strParam = paramxml.Document.ToString();
  57.  
  58.          job.Parameters = strParam;
  59.          scorchSVC.AddToJobs(job);
  60.          scorchSVC.SaveChanges();
  61.                  
  62.       }

Line 35: Creating a new Object or Class Instance of the class created in step 1.

Line 36: Credentials.

Line 38: Retrieve our Runbook data where rbData.Name = the name of the first runbook in the SQL Cluster update series.

Line 42: Retrieve our Runbook parameters.

Line 46: Prepare the data for input parameter 1 (Server or Cluster Name).

Line 50: Prepare the data for input parameter 2 (Indication that we are updating a cluster).

Line 46: Prepare the data for input parameter 3 (email address).

Line 58: Prepare our XML which will be passed to the Orchestrator Web Service.

Line 78: Place the XML into a string for ‘transport’.

Line 80: Add parameters and commit job to Orchestrator Web Service.

That is it. We now have our own custom GIU interface from which to start this particular set up Runbooks. This code can be translated into any C# application for reuse.

 

Video Demonstration:

Let’s take a look at the process in action.

[View:https://www.youtube.com/watch?v=5ldS0IL1cIQ]

Comments (14)

  1. hassan sayed issa20014 says:

    thank you

  2. Anonymous says:

    Sorry Nicholas – this all checks out on my 1154 installation. Here are the migration steps I have taken.

    – Export and Import of Runbooks.

    – Recreation of .CS file.

    – Removed the old .CS file from my website (or other Visual Studio project).

    – Add the new .CS file.

    – Change the coded URI.

    If you are still having issues drop me a line, I will try and assist.

  3. Anonymous says:

    Nicolas thanks for the question. This should be due to an issue with the .CS file created with DataSvcUtil.exe. Did you specify the full URL in when creating the .CS file? Have you verified that the .CS file has been added to solution?

    neilp

  4. Anonymous says:

    Spencer – make sure you execute the console as administrator.

  5. Anonymous says:

    I believe we can β€˜query’ the WebService for status, however it is not clear to me yet what kind of data can be returned, nor how to return this data.

    That said, I am working on a post now that uses some creative methods from which to provide real time and summary feedback into the progress/status of these Runbooks. These examples will be easily modifiable to facilitate the returning of any data from the Orchestrator data bus.

    If you hang tight, I hope to have the post published this week.

    neilp

  6. Anonymous says:

    Just found another blog (zormim.wordpress.com/…/executing-orchestrator-runbooks-from-c) that took this approach to the next level and with the provided item template you can replace all the above code lines with something like:

    string strServer = txtServer.Text;

    string strEmail = txtEmail.Text;

    string strCluster;

    if (chkCluster.Checked)

       strCluster = "True";

    else

       strCluster = "False";

    OrchestratorReference orchestratorReference = new OrchestratorReference();

    orchestratorReference.OrchestratorServiceCredentials = new NetworkCredential("username", "password", "domain");

    orchestratorReference.ClusterUpdates(strServer, strEmail, strCluster);

    Tested it and it work like a charm.

    Mike.

  7. Nicolas says:

    Hi,

    This exercice looks really nice ! πŸ™‚

    I followed it exactly. First of all I had a problem at the first step. When using .NET 3.5 SP1, you only have to enter :

    DataSvcUtil.exe /language:CSharp /out:desiredfilename.cs /uri:http://<SERVERNAME&gt;:81/Orchestrator2012/Orchestrator.svc

    Anyway… It worked exactly as you explained.

    But now, I'm in Visual Studio and trying the code in Windows Forms App. and it doesn't recognize the SystemCenter part of Microsoft.SystemCenter.Orchestrator.WebService.

    Any idea why ?

    Regards

    Nicolas

  8. Nicolas says:

    Hi Neil,

    I finally dealt with my problem. In fact, The class created with the 3.5 .NET DataSvcUtil was empty. I tried again to create it again, but without any success !

    So I tried with fourth version of .NET and it worked perfectly ! Now I can run any of my runbooks from ma Windows Form Application ! πŸ™‚

    I have one new question : In this exercice, we send parameters to the runbook. I guess it's possible to get responses from the runbook with the return data activity… Any idea how ?

    Regards,

    Nicolas

  9. Chris Morrow says:

    My apologies. My immaturity with the product lead me down a rabbit hole. Jobs were pending which led me to the fact that the Runbook Service had crashed so restarting it started handling the queue'd jobs.

  10. Nicolas says:

    Hi Neil,

    I'm back here, because I have a problem using your code with the latest version of Orchestrator (7.0.1154.0) or in my new environnemnt. The problem seems to happen when retrieving Runbook parameters (line 42 of your code). When running the code, I get :

    "Exception has been thrown by the target of an invocation."

    It's annoying, I used your method with Orchestrator RC, and now it doesn't work anymore.

    I'm sure I'm missing something probably stupid, but now I'm out of ideas. Do you have any ?

    I look forward to hearing from you.

    Best Regards,

    Nicolas

  11. Nicolas says:

    Hi Neil,

    Sorry, I had replied to you, but the message didn't go through.

    I don't want to seem rude, so now that I see that my message was not here, I want to apology!

    My problem was in fact just a question of permissions. With my migration and changes of environment, I forgot to give proper permissions to my end users.

    Thank you very much again for your great work!

    Nicolas

  12. Spencer says:

    When I executed the command DataSvcUtil.exe /dataservicecollection /version:2.0 /language:CSharp /out:desiredfilename.cs /uri: http://<SERVERNAME&gt;:81/Orchestrator2012/Orchestrator.svc – no .cs class was outputted to the specified folder. I checked that the orchestrator service was running properly (I got back xml when I went to the url). I also tried version 4.0 but again no class file was made. I even got a 'generation complete' with 0 errors and warnings upon completion. Any idea why this is happening?

    Thanks!

  13. Jake says:

    I have a similar console that I created based off of this article and it works great, thank you for the post. Has anyone figured out what can be used to read data bus output? For example, if I run a runbook that adds 2 numbers together, is there a way
    to "grab" the summed number?

    Thanks!

  14. Arnab says:

    Works like a charm !!