Introduction

This walkthrough will show you how to build a data provider and corresponding query that can be used by an Operations Manager 2012 (OM12) Widget that can be used in a dashboard created in the Operations Console. In this walk through you will learn the following:

  1. Create a [DataProvider] class that contains a [DataCommand] public method. Once the assembly that contains this class is registered in a management pack and is deployed to the server when the management pack is installed, a new dataProvider is then available for access via a query.
  2. Create a class that performs as a “query”. It uses the IDataGateway interface to access the dataProvider that was just implemented. This code, which runs on the client side, provides a public property titled Output. Visual components can bind to this property to receive the data supplied by the dataProvider.

1. Create Data Provider

The DataProvider component contains:

The code must use attributes on classes and methods to identify the dataProvider’s entry points.

1.1 Create the DataProvider Project

  1. Start Visual Studio and select File | New | Project.
  2. Select Visual C#.
  3. In the right pane, select Class Library.
  4. Name the project SimpleDataProvider and click OK.
  5. Delete the Class1.cs file that was automatically added to the project.
  6. Add a new Class:
    1. Right click the project title and select Add | New Item.
    2. Select Class.
    3. Name the class SimpleProvider.cs and click Add.
  7. Add a reference to Microsoft.EnterpriseManagement.Presentation.Core assemblies:
    1. Copy Microsoft.EnterpriseManagement.Presentation.Core.dll from the SimpleDataProvider\bin\Debug folder of the sample files for this walkthrough.
    2. Right-click References in the Solution Explorer and select Add Reference.
    3. Select the Browse tab.
    4. Navigate to the assembly and then click OK.

1.2 Add DataProvider Class

It is possible to create multiple dataProvider classes in the assembly.   Each dataProvider class can have one or more data commands defined.  In this example only a single dataProvider will be created.
  1. Replace the code in SimpleProvider.cs with the following:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Microsoft.EnterpriseManagement.Presentation.DataAccess;
     
    namespaceusing System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text; SimpleDataProvider
    {
        [DataProvider]
        public class SimpleProvider
        {
             
        }
    }

    Notable lines in this code include:

    • Line 1: Creates a local data structure that will be used to receive data from OM12.

1.3 Add Data Command

A data provider must have at least one data command which retrieves the data provided by the data provider. The data command must return one of the following:
  • Simple data type
  • Collection of a simple data type
  • IDataObject
  • Collection of an iDataObject
The command method name can be whatever you choose and it can take whatever parameters you require.   Note that the method must be marked with the [DataCommand] attribute. In this sample the dataProvider does not access any SCOM data or external data. To keep this sample as simple as possible the data provide generates a simple List of strings. You could replace this code with code that accesses a database or some other source of data.
  1. Add the following code to SimpleProvider.cs within the SimpleProvider class:
    [DataCommand]
      public ICollection<string> GetStrings()
      {
          return new List<string> { "Hello", "World", "a", "b", "c" };
      }

    Notable lines in this code include:

    • Line 1: Identifies the method as a DataCommand.
    • Line 4: Generates the data and returns a List of strings.

2 Add Data Provider to Management Pack

2.1 Create the Management Pack project

  1. Create the project:
    1. Right click on the solution and select Add | New Project.
    2. Expand Management Pack  and select Operations Manager.
    3. In the right pane, select Operations Manager 2012 Add-on Management Pack.
    4. Name the project DataProviderPack and click OK.
  2. Add a Management Pack fragment:
    1. Right click on DataProviderPack project in Solution Explorer and select Add | New Item.
    2. Select Empty Management Pack Fragment.
    3. Name the fragment DataProvider.mpx and click Add.

2.2 Add configuration for the assembly:

  1. Add the following code to DataProvider.mpx:
    <ManagementPackFragment>
      <Categories>
        <Category
          ID="Microsoft.EnterpriseManagement.Monitoring.DataProviders.Category"
          Target="SimpleDataProvider"
          Value="Visualization!Microsoft.SystemCenter.Visualization.DataProviderAssembly"/>
      </Categories>
      <Resources>
        <Assembly
          ID="SimpleDataProvider"
          QualifiedName=Categories>
      <Resources>
        <Assembly
          ID="SimpleDataProvider"
          QualifiedName=      FileName="SimpleDataProvider.dll"
          Accessibility="Public"
          HasNullStream="false"/>
      </Resources>
    </ManagementPackFragment>

    Notable lines in this code include:
    • Line 4: Identifies the SimpleDataProvider component as a DataProvider.
    • Lines 10-14: Identify the assembly that contains the dataProvider.

2.3 Add reference to assembly

  1. Right click References and select Add Reference.
  2. On the Projects tab, select SimpleDataProvider and click OK.
  3. Right click SimpleDataProvider and select Properties.
  4. Change the value for Package To Bundle to True.

3 Create Query

The query component, like the data provider component, provides no visualization. Its purpose is to pull data from a data provider.  The data provider component runs on the server while the query component runs on the client.

3.1 Create a Query Project

  1. Create the project:
    1. Right click on the solution and select Add | New Project.
    2. Select Visual C#.
    3. In the right pane, select Class Library.
    4. Name the project SimpleQueryWPF and click OK.
  2. Delete the Class1.cs file that was automatically added to the project.
  3. Add a new Class:
    1. Right click the project title and select Add | New Item.
    2. Select Class.
    3. Name the class Query.cs and click Add.
  4. Add references to the following assemblies:
    • System.ComponentModel.Composition 

    1. Right-click References in the Solution Explorer and select Add Reference.
    2. On the .NET tab locate the assembly and then click OK.
  5. Add references to the following assemblies:
    • Microsoft.EnterpriseManagement.CompositionEngine
    • Microsoft.EnterpriseManagement.CompositionEngine.Extensibility
    • Microsoft.EnterpriseManagement.Presentation.Core
    • Add references to the following assemblies:
      • Microsoft.EnterpriseManagement.CompositionEngine
      • Microsoft.EnterpriseManagement.CompositionEngine.Extensibility
      • Microsoft.Practices.Unity

      1. Copy Microsoft.EnterpriseManagement.Presentation.Core.dll from the SimpleQueryWPF\bin\Debug folder of the sample files for this walkthrough.
      2. Right-click References in the Solution Explorer and select Add Reference.
      3. Select the Browse tab.
      4. Navigate to the assembly and click OK.
    • Add the following directives to Query.cs:
      using System.ComponentModel.Composition;
      using System.ComponentModel;
      using Microsoft.EnterpriseManagement.CompositionEngine;
      using Microsoft.Practices.Unity;
      using Microsoft.EnterpriseManagement.Presentation.DataAccess;

    • Add the following code to Query.cs inside the Query class:
      [Export]
      [PartCreationPolicy(CreationPolicy.NonShared)]
      [ComponentBuildUpRequired]
      public class SimpleQuery: INotifyPropertyChanged, INotifyInitialized
      {
          private bool initialized;
          private ICollection<string> output;
          private int maxItemCount = -1;
       
          public event PropertyChangedEventHandler PropertyChanged;
       
          [Dependency]
          public IDataGateway Gateway { get; set; }
       
          public ICollection<string> Output
          {
              get
              {
                  return this.output;
              }
       
              set
              {
                  this.output = value;
                  this.OnPropertyChanged("Output");
              }
          }
       
          public int MaxItemCount
          {
              get
              {
                  return this.maxItemCount;
              }
       
              set
              {
                  this.maxItemCount = value;
       
                  this.RunQuery();
              set
              {
                  this.maxItemCount = value;
       
                  this            this.OnPropertyChanged("MaxItemCount");
              }
          }
       
          private void OnPropertyChanged(string property)
          {
              if (this.PropertyChanged != null)
              {
                  this.PropertyChanged(this, new PropertyChangedEventArgs(property));
              }
          }
           
          public void Notify()
          {
              this.initialized = true;
              this.RunQuery();
          }
       
          private void RunQuery()
          {
              if (this.initialized &&
                  this.maxItemCount > 0)
              {
                  //Data Access - Call DataProvider
                  var dataObjectsCommand =
                      new AsyncDataCommand<string>("DemoDataProvider!SimpleProvider/GetStrings");
       
        &nb;      //Data Access - Call DataProvider
                  var dataObjectsCommand =
                      new AsyncDataCommand<string>("DemoDataProvider!SimpleProvider/GetStrings"dataObjectsCommand.CommandCompleted += OnDataCommandComplete;
                  this.Gateway.ExecuteAsync(dataObjectsCommand);
              }   
          }
       
          private void OnDataCommandComplete(
              object sender,
              AsyncDataCommandCompletedEventArgs<IEnumerable<string>> args)
          {
              if (args.Error == null)
              {
                  List<string> list = new List<string>();
                  int count = this.maxItemCount;
                  foreach (string s in args.Result)
                  {
                      if (count == 0)
                      {
                          break;
                      }
       
                      list.Add(s);
                      count--;
                  }
       
                  this.Output = list;
              }
          }
      }

      Notable lines in this code include:
      • Lines 1-3: Class attributes that must be assigned to the class.
      • Line 6: Declares the bool variable initialized. The design of this class is that the query should not return data unless this variable is true. This variable is set to true in the Notify() method, which is called by OM12() when all bindings have been initialized.
      • Line 13: Declares a variable of the type IDataGateway. The IDataGateway class is used to make server side calls.
      • Lines 15-27: Define the public property OutPut. This is a required property for a query. 
      • Lines 59-71: Make the call to the dataProvider.

3.2 Create a Silverlight Query Project

The Silverlight version of the SimpleQuery will share the xaml and code behind from the WPF project.

  1. Create the project:
    1. Right click on the solution and select Add | New Project.
    2. Expand Visual C# and select Silverlight.
    3. In the right pane, select Silverlight Class Library.
    4. Name the project SimpleQuerySL and click OK.
    5. When prompted for the Silverlight version, select Silverlight 4 and click OK.
  2. Delete the Class1.cs file that was automatically added to the project.
  3. Add a link to the query in the WPF project:
    1. Right click the project title and select Add | Existing Item.
    2. Navigate to the SimpleQueryWPF folder.
    3. Select Query.cs.
    4. Click the dropdown on the Add button and select Add as Link.
  4. Add a reference to the following assemblies:
    •   System.ComponentModel.Comp;font-size:12px;">Add a link to the query in the WPF project:
      1. Right click the project title and select Add | Existing Item.
      2. Navigate to the SimpleQueryWPF folder.
      3. Select Query.cs.
      4. Click the dropdown on the Add button and select Add as Link.
    • Add a reference to the following assemblies:


      1. Right-click References in the Solution Explorer and select Add Reference.
      2. On the .NET tab locate the assembly and then click OK.
    • Add references to the Silverlight version of the following assemblies.  
      • Microsoft.EnterpriseManagement.CompositionEngine
      • Microsoft.EnterpriseManagement.CompositionEngine.Extensibility
      • Microsoft.EnterpriseManagement.Presentation.Core
      • Microsoft.Practices.Unity.Silverlight

      1. Copy Microsoft.EnterpriseManagement.Presentation.Core.dll from the SimpleQuerySL\bin\Debug folder of the sample files for this walkthrough.
      2. Right-click References in the Solution Explorer and select Add Reference.
      3. Select the Browse tab.
      4. Navigate to the assembly and click OK.

4 Create Visualization

A user control is needed to display the data obtained from the data provider.

4.1 Create Control Project

  1. Create the project:
    1. Right click on the solution and select Add | New Project.
    2. Select Visual C#.
    3. In the right pane, select WPF User Control Library.
    4. Name the project TestWPF and click OK.
    5. Right click the TestWPF project and select Properties.
    6. In Target framework, select .NET Framework 4.
  2. Delete the UserControl1.xaml file that was automatically added to the project.
  3. Add a new user control:
    1. Right click the project title and select Add | New Item.
    2. Select Visual C#.
    3. In the right pane, select User Control (WPF).
    4. Name the user control TestControl.xaml and click Add.
  4. Add references to the following assemblies:
    • System.ComponentModel.Composition

    1. Right-click References in the Solution Explorer and select Add Reference.
    2. On the .NET tab locate the assembly and then click OK.
  5. Add references to the following assemblies:
    • Microsoft.EnterpriseManagement.CompositionEngine
    • Microsoft.EnterpriseManagement.Presentation.Core

    1. Copy Microsoft.EnterpriseManagement.Presentation.Core.dll from the TestWPF\bin\Debug folder of the sample files for this walkthrough.
    2. Right-click References in the Solution Explorer and select Add Reference.

      • Microsoft.EnterpriseManagement.CompositionEngine
      • Microsoft.EnterpriseManagement.Presentation.Core

      1. Copy Microsoft.EnterpriseManagement.Presentation.Core.dll from the TestWPF\bin\Debug folder of the sample files for this walkthrough.
      2. Right-click References in the Solution Explorer and select Add Referefont-size:11pt;">Select the Browse tab.
      3. Navigate to the assembly and click OK.

    4.2 Configure the User Control

    1. Replace the XML in TestControl.xaml with the following:
      <UserControl x:Class="TestWPF.TestControl"
          mc:Ignorable="d"
          d:DesignHeight="115" d:DesignWidth="395">
          <Grid x:Name="LayoutRoot" Background="White" Height="87" Width="372">
              <Grid.ColumnDefinitions>
                  <ColumnDefinition Width="Auto"/>
                  <ColumnDefinition Width="*"/>
              </Grid.ColumnDefinitions>
              <TextBlock Grid.Column="0">List from SimpleDataProvider:  </TextBlock>
              <ListBox x:Name="listBox" Grid.Column="1"></ListBox>
          </Grid>
      </UserControl>

      Notable lines in this code include:
      • Lines 15: Places a list box control on the page. This list box will display the set of strings received from the data provider.

    2. Replace the contents of the code behind TestControl.xaml.cs with the following code:
      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Net;
      using System.Windows;
      using System.Windows.Controls;
      using System.Windows.Documents;
      using System.Windows.Input;
      using System.Windows.Media;
      using System.Windows.Media.Animation;
      using System.Windows.Shapes;
      using System.ComponentModel;
      using System.ComponentModel.Composition;
       
      using Microsoft.EnterpriseManagement.CompositionEngine;
       
      namespace TestWPF
      {
          [Export]
          [PartCreationPolicy(CreationPolicy.NonShared)]
       
      using Microsoft.EnterpriseManagement.CompositionEngine;
       
      namespace TestWPF
      {
      &nbdiv style="background-color:white;">    public partial class TestControl : UserControl, INotifyPropertyChanged
       
          {
              private ICollection<string> _stringList;
              public ICollection<string> StringList
              {
                  get
                  {
                      return this._stringList;
                  }
       
                  set
                  {
                      if (value != null)
                      {
                          this._stringList = value;
                          this.listBox.ItemsSource = value;
                      }
                  }
              }
       
       
              public TestControl()
              {
                  InitializeComponent();
              }
       
              public event PropertyChangedEventHandler PropertyChanged;
       
              protected void OnPropertyChanged(string propertyName)
              {
                  if (PropertyChanged != null)
                  {
                      PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                  }
              }
       
          }
      }