image

Orchestrator, C# and Runbooks

At this point of the game, we have a pretty good feel for using the Designer, and we also have been playing with the new Silverlight console to play around with the runbook’s, but now its time to get even more curious with the ODATA Service’s.  If you have been watching the blogs and webcasts; some demo’s of using the Excel Pivot tables have been created to show off the power of this service, with very little effort needed to take advantage.

However, I have different ideas; and today I am going to try and share a proof on concept Console App in C# to integrate with the ODATA Service.

Disclaimer: Now, I need to be very clear here; I am not a developer, although I do enjoy pretending to be, therefore its very likely there are much smarter ways to achieve the goals, but if there is, I don’t know them yet! – so please comment…

Visual Studio and Web Services

Great, let’s start off the session with a nice new Project; I am going to call this SCOrchServices for obvious reasons

image

Now, let’s not waste any time at all. We are going to use the power of to tool, and create a Class to help us bind and communicate with the ODATA imageinterface on Orchestrator. So navigate over to your Solution Explorer and right click on the Project Name to get the context menu. From there I need you to select the option Add Service Reference…

This will present us with the Add Service Reference Dialogue, where will will type in the address of our Orchestrator 2012 Web Service. Once we have done that all we need to do next is click on the Go button and wait a few moments for the magic to work.

Update for RC and Newer – the ODATA link is now at http://servername:port/Orchestrator2012/Orchestrator.svc/

image

 

 

 

 

 

 

Once control is returned, we will now see in the Services pane the new context OrchestratorContext which you can expand to see all the goodies which are on offer.

Now, let’s wrap up our work here, and in the Namespace field we will name this new reference as SCOrchestratorOData which we will be calling on in a few moments.

Hit the OK button, and before you know it, your solution explorer will now have a new entry, with this new reference ready for us to start using.

Helper Class

So, that was pretty easy, Now lets get back to do some real work, this time we are going to see if we can add a few lines of code with the objective of using this new web service reference to get a list of all the Run Books which are currently published on the Orchestrator server.

Rather then repeat code over many times, I am going to also create a helper class which I will simple call SCOrchestrator. To do this, once again on the project name right click and from the context menu we are going to select Add > Class and when the file dialogue appears we will just set the name of the file to be SCOrchestrator.cs to match our class name.

VS will then stub out the blank class for us, and we can start typing.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SCOrchServices
{
    class SCOrchestrator
    {
        private string serviceRoot;
        private SCOrchestratorOData.OrchestratorContext context;

        public string ServiceRoot
        {
            get { return serviceRoot; }
            set { serviceRoot = value; }
        }

        public SCOrchestratorOData.OrchestratorContext Context
        {
            get { return context; }
            set { context = value; }
        }

        public void Initialize(string serviceRoot)
        {
            // Constructor for the Class
            ServiceRoot = serviceRoot;
            context = new SCOrchestratorOData.OrchestratorContext(new Uri(serviceRoot));

            // Let's try and use the Default Credentials which we are using under this windows user account
            context.Credentials = System.Net.CredentialCache.DefaultCredentials;

            // Alternatively - you could pass in credentials of your choice
            //orchestrator.Credentials = new System.Net.NetworkCredential("scorchUser", "!Pass123", "domain");
        }

    }
}

Ok, Fair enough, it does look a bit odd, so lets break it down so we can make some logic of what’s going on here. I am starting off the class with 2 private variables, the first is a string to hold the name of the URL to our actual web service we plan to connect with. And yes we did provided that when we used the Add Service Reference earlier, but that was just to make the template class for us, we don’t actually ever need to use that again if we so wish; but since my lab only has the one Orchestrator server, I am going to do exactly that, and use the same server URL in a few moments.

The second Variable I am creating is a little different, If you look closely you will see that we are creating a variable of base type SCOrchestratorOData which from memory you will recall is the namespace which we only just defined as we had the wizard add the Service Reference. The Context part of this is the Glue which will help us tie our application via the service reference back to the actual OData feed.

Finally, I actually make these two private variables public as is, with to public methods; if we need to tweak later, then this will keep things a bit cleaner.

    class SCOrchestrator
    {
        private string serviceRoot;
        private SCOrchestratorOData.OrchestratorContext context;

        public string ServiceRoot
        {
            get { return serviceRoot; }
            set { serviceRoot = value; }
        }

        public SCOrchestratorOData.OrchestratorContext Context
        {
            get { return context; }
            set { context = value; }
        }

 

Now this next method is much more interesting (I could have overloaded the constructor, but figured this might be easier to explain). The purpose here is to Initialize our connection to the Orchestrator Web service, which we do in two steps. First we will use the magic of the new Service Reference class SCOrchestratorOData to create a new connection context for us.

This takes in the serviceRoot, which I already explained is the URL to the ODATA Web Service; then once the method has make the link, we store that in the context which we will use for all further interaction with Orchestrator.

Now, the second step here is that Orchestrator needs us to identify ourselves. So, using context we can pass in the Credentials and in the active code, we will use our currently logged in credentials for the domain; but the sample code i have commented out, we can pass in any identification manually if needed Winking smile

        public void Initialize(string serviceRoot)
        {
            // Constructor for the Class
            ServiceRoot = serviceRoot;
            context = new SCOrchestratorOData.OrchestratorContext(new Uri(serviceRoot));

            // Let's try and use the Default Credentials which we are using under this windows user account
            context.Credentials = System.Net.CredentialCache.DefaultCredentials;

            // Alternatively - you could pass in credentials of your choice
            //orchestrator.Credentials = new System.Net.NetworkCredential("scorchUser", "!Pass123", "domain");
        }

Main Program

Right, lets get this stuff working and, see how simple it really is to work with Orchestrator and Visual Studio.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SCOrchServices
{
    class Program
    {
        static void Main(string[] args)
        {
            SCOrchestrator scorch = new SCOrchestrator();
            scorch.Initialize("http://orchestrator:81/Orchestrator.svc");

            var runbooks = from runbook in scorch.Context.Runbooks
                           select runbook;

            foreach (var item in runbooks)
            {
                Console.WriteLine("Name: " + item.Name + "  ID: " + item.Id);
            }

            Console.ReadKey();
        }
    }
}

Again, most of the work was already done for us when we created the new project in Visual Studio.

This time the first two lines of code, we are just creating an instance of our helper class, and then Initializing the connection.

Once that is done, we will make a variable called runbooks where using a simple Linq query we will grab from the RunBooks Context (scorch.Context.Runbooks) all the available runbooks, and store the results in the runbooks variable.

image

Finally, we just loop trough all the data which is now stored in the runbooks variable, and place them in a temporary variable called item which we can then use to expose the currently available information for this entry. As you can see from the screen shot Visual Studio is very helpful, thanks in full to the ODATA services, and will show in the intelligence all the different data types we can display in this context, so no more guessing Smile

 

Testing 123…

So, what are you waiting for, run the program! Assuming you have no errors, and have authenticated correctly, then your console should now be presenting you with a list of runbooks published on the server.

image

 

Easy, Yah!!!

Check back, we will start a Runbook next!

  • Pingback: Windows Azure and Cloud Computing Posts for 8/19/2011+ - Windows Azure Blog

  • Pingback: Building Stuff | Using .NET to trigger System Center Orchestrator

  • Nicolas Hoffman

    Hi,

    First of all, thank you for your nice blog, it seems verry complete and usefull !

    I’m trying to do like you did, but I’m having trubles at the verry beginning… When I try to add service reference in Visual C# Espress, I get this :

    There was an error downloading ‘http://svr-orchestra:81/Orchestrator.svc/’.
    The request failed with the error message:

    Request Error
    BODY { color: #000000; background-color: white; font-family: Verdana; margin-left: 0px; margin-top: 0px; } #content { margin-left: 30px; font-size: .70em; padding-bottom: 2em; } A:link { color: #336699; font-weight: bold; text-decoration: underline; } A:visited { color: #6699cc; font-weight: bold; text-decoration: underline; } A:active { color: #336699; font-weight: bold; text-decoration: underline; } .heading1 { background-color: #003366; border-bottom: #336699 6px solid; color: #ffffff; font-family: Tahoma; font-size: 26px; font-weight: normal;margin: 0em 0em 10px -20px; padding-bottom: 8px; padding-left: 30px;padding-top: 16px;} pre { font-size:small; background-color: #e5e5cc; padding: 5px; font-family: Courier New; margin-top: 0px; border: 1px #f0f0e0 solid; white-space: pre-wrap; white-space: -pre-wrap; word-wrap: break-word; } table { border-collapse: collapse; border-spacing: 0px; font-family: Verdana;} table th { border-right: 2px white solid; border-bottom: 2px white solid; font-weight: bold; background-color: #cecf9c;} table td { border-right: 2px white solid; border-bottom: 2px white solid; background-color: #e5e5cc;}

    Request Error
    The server encountered an error processing the request. The exception message is ‘The underlying provider failed on Open.’. See server logs for more details. The exception stack trace is:
    at System.Data.EntityClient.EntityConnection.OpenStoreConnectionIf(Boolean openCondition, DbConnection storeConnectionToOpen, DbConnection originalConnection, String exceptionCode, String attemptedOperation, Boolean& closeStoreConnectionOnFailure)
    at System.Data.EntityClient.EntityConnection.Open()
    at System.Data.Objects.ObjectContext.EnsureConnection()
    at System.Data.Objects.ObjectContext.ExecuteFunction(String functionName, ObjectParameter[] parameters)
    at Microsoft.SystemCenter.Orchestrator.WebService.OrchestratorContext.OnContextCreated()
    at invoke_constructor()
    at System.Data.Services.DataService`1.CreateProvider()
    at System.Data.Services.DataService`1.HandleRequest()
    at System.Data.Services.DataService`1.ProcessRequestForMessage(Stream messageBody)
    at SyncInvokeProcessRequestForMessage(Object , Object[] , Object[] )
    at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)
    at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
    at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)
    at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc& rpc)
    at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)

    –.
    Metadata contains a reference that cannot be resolved: ‘http://svr-orchestra:81/Orchestrator.svc/’.
    The HTTP request is unauthorized with client authentication scheme ‘Anonymous’. The authentication header received from the server was ‘Negotiate,NTLM’.
    The remote server returned an error: (401) Unauthorized.

    Any idea of what this means ?

    • http://www.damianflynn.com damian.flynn

      Nicolas,

      The reference changed with RC and is now http://srv-orchestartor:81/Orchestrator2012/Orchestrator.svc/

      this should get you sorted

  • Nicolas Hoffman

    OK, sorry about previous comment, I should have read the entire blog before writting… If anyone wants to do like me, please visit :
    http://www.damianflynn.com/2011/11/28/orchestrator-2012-rc-web-services-error-console-not-working/
    before making a stupid comment.

    Sir, I thank you for your nice work ! :)

    • http://www.damianflynn.com damian.flynn

      Nicolas, I have added a reference in the post, as its not obvious enough for the new ODATA after RC location.

      if you need more assistance, please let me know.
      -damian

  • Pingback: Using .NET C# and the Orchestrator Web Service « Developer's Closet

7 Comments

Windows Azure and Cloud Computing Posts for 8/19/2011+ - Windows Azure Blog 19-08-2011, 22:10

[...] can read his articles on Orchestrator here. He starts with an article outlining the web service itself and how to work with it in Visual Studio, follows this up with guidance on how to start a Runbook [...]

Nicolas Hoffman 14-02-2012, 13:30

Hi,

First of all, thank you for your nice blog, it seems verry complete and usefull !

I’m trying to do like you did, but I’m having trubles at the verry beginning… When I try to add service reference in Visual C# Espress, I get this :

There was an error downloading ‘http://svr-orchestra:81/Orchestrator.svc/’.
The request failed with the error message:

Request Error
BODY { color: #000000; background-color: white; font-family: Verdana; margin-left: 0px; margin-top: 0px; } #content { margin-left: 30px; font-size: .70em; padding-bottom: 2em; } A:link { color: #336699; font-weight: bold; text-decoration: underline; } A:visited { color: #6699cc; font-weight: bold; text-decoration: underline; } A:active { color: #336699; font-weight: bold; text-decoration: underline; } .heading1 { background-color: #003366; border-bottom: #336699 6px solid; color: #ffffff; font-family: Tahoma; font-size: 26px; font-weight: normal;margin: 0em 0em 10px -20px; padding-bottom: 8px; padding-left: 30px;padding-top: 16px;} pre { font-size:small; background-color: #e5e5cc; padding: 5px; font-family: Courier New; margin-top: 0px; border: 1px #f0f0e0 solid; white-space: pre-wrap; white-space: -pre-wrap; word-wrap: break-word; } table { border-collapse: collapse; border-spacing: 0px; font-family: Verdana;} table th { border-right: 2px white solid; border-bottom: 2px white solid; font-weight: bold; background-color: #cecf9c;} table td { border-right: 2px white solid; border-bottom: 2px white solid; background-color: #e5e5cc;}

Request Error
The server encountered an error processing the request. The exception message is ‘The underlying provider failed on Open.’. See server logs for more details. The exception stack trace is:
at System.Data.EntityClient.EntityConnection.OpenStoreConnectionIf(Boolean openCondition, DbConnection storeConnectionToOpen, DbConnection originalConnection, String exceptionCode, String attemptedOperation, Boolean& closeStoreConnectionOnFailure)
at System.Data.EntityClient.EntityConnection.Open()
at System.Data.Objects.ObjectContext.EnsureConnection()
at System.Data.Objects.ObjectContext.ExecuteFunction(String functionName, ObjectParameter[] parameters)
at Microsoft.SystemCenter.Orchestrator.WebService.OrchestratorContext.OnContextCreated()
at invoke_constructor()
at System.Data.Services.DataService`1.CreateProvider()
at System.Data.Services.DataService`1.HandleRequest()
at System.Data.Services.DataService`1.ProcessRequestForMessage(Stream messageBody)
at SyncInvokeProcessRequestForMessage(Object , Object[] , Object[] )
at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)
at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)

–.
Metadata contains a reference that cannot be resolved: ‘http://svr-orchestra:81/Orchestrator.svc/’.
The HTTP request is unauthorized with client authentication scheme ‘Anonymous’. The authentication header received from the server was ‘Negotiate,NTLM’.
The remote server returned an error: (401) Unauthorized.

Any idea of what this means ?

damian.flynn 14-02-2012, 14:36

Nicolas,

The reference changed with RC and is now http://srv-orchestartor:81/Orchestrator2012/Orchestrator.svc/

this should get you sorted

Nicolas Hoffman 14-02-2012, 14:31

OK, sorry about previous comment, I should have read the entire blog before writting… If anyone wants to do like me, please visit :
http://www.damianflynn.com/2011/11/28/orchestrator-2012-rc-web-services-error-console-not-working/
before making a stupid comment.

Sir, I thank you for your nice work ! :)

damian.flynn 14-02-2012, 14:34

Nicolas, I have added a reference in the post, as its not obvious enough for the new ODATA after RC location.

if you need more assistance, please let me know.
-damian

image