ArcGIS Runtime SDK for WPF - Library Reference
ClientCertificate Property
See Also  Example
ESRI.ArcGIS.Client.Printing Namespace > PrintTask Class : ClientCertificate Property

Gets or sets the client certificate that is sent to the host and used to authenticate the request.

Syntax

Visual Basic (Declaration) 
Public Property ClientCertificate As X509Certificate
C# 
public X509Certificate ClientCertificate {get; set;}

Remarks

A client certificate is an electronic document which uses a digital signature to bind a public key with an identity. A client certificate is used to verify that a public key belongs to an individual or an organization. When a client certificate is valid, access to secured content over the https:// is enabled. Client certificates fall under the technology umbrella known as a Public-Key Infrastructure (PKI). PKI is a large complex body of standards, policies, protocols, and practices that are beyond the scope this documentation. The following Microsoft document should give the developer a starting point to understand PKI: Public Key Infrastructure.

ArcGIS Server version 10.1 and higher has the ability to leverage PKI solutions in 'Commercial Off the Shelf' (COTS) Web servers such as: Microsoft Internet Information Server (IIS), Oracle WebLogic, IBM WebSphere, etc. through the use of the ArcGIS Web Adaptor. The requirements for using PKI in ArcGIS Server include:

  1. The ArcGIS Web Adaptor must be setup as the gateway to ArcGIS Server.
  2. The Web Server hosting the ArcGIS Web Adaptor must be configured to require client certificates for user authentication.
  3. ArcGIS Server Site must be configured to: (a) Delegate user authentication to the Web Tier and (b) Use an identity store (LDAP, Windows Active Directory, etc.) supported by the Web Server.

When a request is made for a resource on ArcGIS Server, the Web Server will authenticate the user by validating the client certificate provided. The request (along with the user name) is then forwarded to ArcGIS Server via the Web Adaptor. ArcGIS Server will verify that the specified user has access to the requested resource before sending back the appropriate response. For more information on using PKI techniques to set up and use client certificates, see the ArcGIS Server documentation.

The ArcGIS Runtime for WPF requires supplying a valid Microsoft System.Security.Cryptography.X509Certificates.X509Certificate object as the .ClientCertificate Property in order to gain access to a secured (https://) ArcGIS Server web service based upon PKI. The Microsoft System.Security.Cryptography.X509Certificates Namespace API documentation provides a starting point for developers to learn how to programmatically access X509Certificate objects. If no client certificates have been set up on a client machine and a user tries to access using an X509Certificate from your custom ArcGIS WPF application, a Windows Security dialog stating "No certificate available. No certificates meet the application. Click OK to continue" will appear:

Try to access an X509Certificate when none are installed on the client computer.

Whenever an ArcGIS Runtime for WPF based application uses PKI to secure web services, it is important that error checking be added to the application to ensure that the correct X509Certificate is used to access those secured web services. If a user of your ArcGIS WPF client application provides/uses an X509Certificate that is not accepted by the PKI security set up on the ArcGIS Server machine, then an error will be thrown.

Depending on the particular ArcGIS Runtime for WPF object that is used, the developer will need to write code in the appropriate error handling event. For example: an ArcGISDynmaicMapServiceLayer should have error trapping code in the InitializationFailed Event; a QueryTask should have error trapping code in the Failed Event, a PrintTask should have error trapping code in the ExecuteCompleted Event (via the PrintEventArgs), etc.

The .ClientCertificate Property has been added to numerous ArcGIS Runtime for WPF objects. Accessing and using an X509Certificate is basically the same for each of the ArcGIS Runtime for WPF objects with a .ClientCertificate Property. There are code examples of using the X509Certificate in the DynamicMapServiceLayer.ClientCertificate Property, ArcGISTiledMapServiceLayer.ClientCertificate Property, Printing.PrintTask.ClientCertificate Property (code-behind only options) and FeatureLayer.ClientCertificate Property (Model-View-View-Model (MVVM) pattern using XAML and code-behind). Remember the key to accessing a PKI based secured ArcGIS Server web service is to first provide the appropriate .ClientCertificate Property credentials during construction of the object and prior to using (i.e Set/Write) any of the other properties/methods of the ArcGIS Runtime for WPF object, otherwise an error accessing that object will result.

It is not possible to use the PrintTask on ArcGIS Server layers that are secured with Public-Key Infrastructure (PKI) client certificates. This introduces security holes in trying to pass client certificates from one web server to another. This limitation even applies to a single ArcGIS Server machine that has both secured layer web services and a secured PrintTask. If you attempt to use a PrintTask on a PKI secured layer with a client certificate it will throw and error with the text similar to the following:

"Error code '400': Unable to complete operation.' Error executing tool.: Layer "[YOUR_LAYER_NAME]": Unable to connect to map server at https://[YOUR_SECURE_WEB_SERVER]/arcgis/rest/services/[YOUR_SERVICE]/MapServer. Failed to execute (Export Web Map). Failed to execute (Export Web Map Task)."

Error code 400 when trying to use the PrintTask on a secured layer.

NOTE: It is possible however to use a PKI secured PrintTask to print layers that are on public ArcGIS Servers. See the code example in this document of how to do this.

Property Value

The client certificate used for authentication.

Example

How to use:

When the application loads, enter a correct Url to a secured ArcGIS Server PrintTask using PKI concepts based on a 'synchronous geoprocessing task'. Then click the 'ExecuteAsync' button to generate a .JPG image returned in an internet browser. Two dialogs will apper prompting the user for the correct certificate that will enable them to access the secured PrintTask service. The first dialog was baked into the code-behind for the purpose of setting the PrintTask.ClientCertificate Property. The second dialog asks for the same credential information to enable the secured PrintTask to display result content in the WebBrowser. 'Status Informaton' messages will display to provide updates on the PrintTask operation. Experiment by clicking the 'ExecuteAsync' button in rapid succession (ie. before the PrintTask has a chance to complete generating an image/.pdf file to better understand how a 'synchronous geoprocesing task' works.

NOTE: This code example is nearly identical to the ESRI.ArcGIS.Client.PrintTask.ExecuteAsync(PrintParameters,Object) Method code example with the added enhancements to account for accessing the PrintTask web service via a PKI secured ArcGIS Server using the PrintTask.ClientCertificate Property.

The XAML code in this example is used in conjunction with the code-behind (C# or VB.NET) to demonstrate the functionality.

The following screen shot corresponds to the code example in this page.

Using a PKI security based PrintTask.ClientCertificate Property.

XAMLCopy Code
<Grid x:Name="LayoutRoot" Background="White">
  <esri:Map Background="White" HorizontalAlignment="Left" Margin="0,312,0,0" 
        Name="MyMap" VerticalAlignment="Top" WrapAround="True" Height="300" Width="578"
        Extent="-10929488.234,4525208.388,-10906776.553,4535252.104">
    <esri:Map.Layers>
      <esri:LayerCollection>
      
        <!-- Add some layers to the Map Control. -->
        <esri:ArcGISTiledMapServiceLayer 
              Url="http://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer" />
        <esri:FeatureLayer Mode="OnDemand" DisableClientCaching="True" 
              Url="http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/Petroleum/KSWells/MapServer/0" />
        
      </esri:LayerCollection>
    </esri:Map.Layers>
  </esri:Map>
  
  <!-- Url -->
  <Label Height="25" HorizontalAlignment="Left" Margin="8,174,0,0" Name="Label_Url" 
         VerticalAlignment="Top" Width="31" Content="Url:"/>
  <TextBox Height="23" HorizontalAlignment="Left" Margin="8,196,0,0" Name="TextBox_Url" 
           VerticalAlignment="Top" Width="570" FontSize="10" />
  
  <!-- Buttons to perform the work. -->
  <Button Content="ExecuteAsync" Height="39" Width="201" HorizontalAlignment="Left" Margin="12,226,0,0" 
          Name="Button_ExecuteAsync" VerticalAlignment="Top" Click="Button_ExecuteAsync_Click" IsEnabled="True"/>
  <Button Content="CancelAsync" Height="35" Width="201" HorizontalAlignment="Left" Margin="12,270,0,0" 
          Name="Button_CancelAsync" VerticalAlignment="Top" Click="Button_CancelAsync_Click" IsEnabled="False"/>
  
  <!-- Provide PrintTask information messages. -->
  <Label Height="25" HorizontalAlignment="Left" Margin="229,220,0,0" Name="Label_StatusInfo" 
         VerticalAlignment="Top" Width="120" Content="Status Information:"/>
  <ListBox Height="64" HorizontalAlignment="Left" Margin="229,242,0,0" Name="ListBox_StatusInformation" 
           VerticalAlignment="Top" Width="349" />
  
  <!-- Add a WebBrowser to display the results from the PrintTask operation. -->
  <Label Content="WebBrowser to view PrintTask results:" Height="28" HorizontalAlignment="Left" Margin="0,632,0,0" 
         Name="Label1" VerticalAlignment="Top" />
  <WebBrowser Height="300" HorizontalAlignment="Left" Margin="0,654,0,0" Name="WebBrowser1" 
              VerticalAlignment="Top" Width="578" />
  
  <!-- Provide the instructions on how to use the sample code. -->
  <TextBlock Height="168" HorizontalAlignment="Left" Name="TextBlock1" VerticalAlignment="Top" Width="578" 
             TextWrapping="Wrap" Text="When the application loads, enter a correct Url to a secured ArcGIS Server PrintTask using PKI concepts 
             based on a 'synchronous geoprocessing task'. Then click the 'ExecuteAsync' button to generate a .JPG 
             image returned in an internet browser. Two dialogs will apper prompting the user for the correct 
             certificate that will enable them to access the secured PrintTask service. The first dialog was 
             baked into the code-behind for the purpose of setting the PrintTask.ClientCertificate Property. 
             The second dialog asks for the same credential information to enable the secured PrintTask to 
             display result content in the WebBrowser. 'Status Informaton' messages will display to provide 
             updates on the PrintTask operation. Experiment by clicking the 'ExecuteAsync' button in rapid 
             succession (ie. before the PrintTask has a chance to complete generating an image/.pdf file to 
             better understand how a 'synchronous geoprocesing task' works.
             NOTE: This code example is nearly identical to the 
             ESRI.ArcGIS.Client.PrintTask.ExecuteAsync(PrintParameters,Object) Method code example with the 
             added enhancements to account for accessing the PrintTask web service via a PKI secured ArcGIS Server 
             using the PrintTask.ClientCertificate Property." />
  
</Grid>
C#Copy Code
// Create a Global (aka. Member) variable for the PrintTask object that will be used in other 
// parts of the application.
private ESRI.ArcGIS.Client.Printing.PrintTask _PrintTask;
            
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// PrintTask.ClientCertificate code:
//
// Global (i.e. Member) variable for the certificate.
public System.Security.Cryptography.X509Certificates.X509Certificate _TheClientCertificate = new System.Security.Cryptography.X509Certificates.X509Certificate();
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            
public MainWindow()
{
  InitializeComponent();
  
  // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  // PrintTask.ClientCertificate code:
  //
  // TODO: Provide a valid PrintTask.Url for a "synchronous geoprocessing task". It will be a secured ArcGIS Server that
  // takes advantage of PKI security (i.e. https://).
  TextBox_Url.Text = "https://www.yoursite.com/arcgis/rest/services/Utilities/PrintingTools/GPServer/Export20Web20Map%20Task";
  // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  
  // Set the _PrintTask variable to a new instance of the PrintTask Class.
  _PrintTask = new ESRI.ArcGIS.Client.Printing.PrintTask();
  
  // Prevent the internet browser from using a cache for the PrintTask operations.
  _PrintTask.DisableClientCaching = true;
  
  // Set the PrintTask.Url from what is entered in the TextBox.
  _PrintTask.Url = TextBox_Url.Text;
  
  // Wire up an Event Handler for the PrintTask.ExecuteCompleted Event.
  _PrintTask.ExecuteCompleted += printTask_ExecuteCompleted;
}
            
private void Button_ExecuteAsync_Click(object sender, System.Windows.RoutedEventArgs e)
{
  // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  // PrintTask.ClientCertificate code:
  //
  // Create a new instance of a X509Store object (which is a physical store where certificates are persisted and managed).
  // The X509Store object uses a StoreName based upon a 'personal certificate' and a StoreLocation for the user that 
  // is currently logged in. The X509Store is accessed as ReadOnly to obtain the certificate. 
  // NOTE: Don't forget to add a Reference to the System.Security Assembly. 
  System.Security.Cryptography.X509Certificates.X509Store theX509Store = null;
  System.Security.Cryptography.X509Certificates.StoreName theStoreName = System.Security.Cryptography.X509Certificates.StoreName.My;
  System.Security.Cryptography.X509Certificates.StoreLocation theStoreLocation = System.Security.Cryptography.X509Certificates.StoreLocation.CurrentUser;
  theX509Store = new System.Security.Cryptography.X509Certificates.X509Store(theStoreName, theStoreLocation);
  theX509Store.Open(System.Security.Cryptography.X509Certificates.OpenFlags.ReadOnly);
  
  // Obtain the collection of certificates in the X509Store. Note: depending on your organization there may multiple certificates!
  System.Security.Cryptography.X509Certificates.X509Certificate2Collection certificates = theX509Store.Certificates;
  
  // Display a dialog that prompts the user to select the correct certificate from the list of certificates available in the X509Store.
  // If the correct certificate is chosen and the user clicks the button to execute the secured PrintTask it should
  // display the results in the WebBrowser control. If a wrong certificate is chosen and then user then clicks the button to load the 
  // secured PrintTask, the PrintTask.ExecuteComplete event will fire and display an error message with text similar to the 
  // following: "The remote server returned an error: (403) Forbidden." or "The remote server returned error: (401) Unauthorized."
  // NOTE: There will actually be 2 dialogs that appear asking for certificate credentials. The first dialog is the one that is
  // invoked as a result of the X509Certificate2UI.SelectFromCollection() call. The second dialog automatically appears as a result
  // of adding content into the WebBrowser.
  string theTitle = "Select a certificate";
  string theMessage = "Select the certificate to use for authentication to access the secured PrintTask.";
  System.Security.Cryptography.X509Certificates.X509SelectionFlag theSelectionFlag = System.Security.Cryptography.X509Certificates.X509SelectionFlag.SingleSelection;
  certificates = System.Security.Cryptography.X509Certificates.X509Certificate2UI.SelectFromCollection(certificates, theTitle, theMessage, theSelectionFlag);
  
  // Only continue if at least one certificate is chosen.
  if (certificates.Count > 0)
  {
    // Set the X509Certificate global variable. This will be used in constructing the PrintTask. 
    _TheClientCertificate = certificates[0];
    
    // Set the PrintTask.ClientCertificate to enable printing from the secured web service. 
    _PrintTask.ClientCertificate = _TheClientCertificate;
  }
  // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  
  // Define the settings for rendering the image/.pdf on the ArcGIS Server.
  
  // Define the ExportOptions.
  ESRI.ArcGIS.Client.Printing.ExportOptions myExportOptions = new ESRI.ArcGIS.Client.Printing.ExportOptions();
  myExportOptions.Dpi = 96; //96 DPI is typical Window OS setting.
  myExportOptions.OutputSize = new Size(MyMap.ActualWidth, MyMap.ActualHeight); // Use the dimensions of the Map
  
  // Define the PrintParameters.
  ESRI.ArcGIS.Client.Printing.PrintParameters myPrintParameters = new ESRI.ArcGIS.Client.Printing.PrintParameters(MyMap);
  myPrintParameters.ExportOptions = myExportOptions; // Use the ExportOptions defined earlier.
  myPrintParameters.LayoutTemplate = "MAP_ONLY"; // Look to the REST service to see what layout templates are supported.
  myPrintParameters.Format = "JPG"; // Look to the REST service to see what image formats are supported.
  
  // NOTE: 
  // If you try to submit more that one 'synchronous geoprocessing task' via PrintTask.ExecuteAsync at a time 
  // using the ExecuteAsync methadology you will get a Visual Studio (Runtime) error: 
  // NotSupportedException was unhandled by user code. "Task does not support concurrent  I/O operations. Cancel 
  // the pending request or wait for it to complete." 
  // In order to overcome this, use the PrintTask.IsBusy Property and take action accordingly.
  
  if (_PrintTask.IsBusy == true)
  {
    // There is an existing 'synchronous geoprocessing task' PrintTask running. 
    
    // Use a simple MessageBox to get user direction on whether to stay with the currently running 'synchronous 
    // geoprocessing task' PrintTask or cancel it and start another one.
    System.Windows.MessageBoxResult myMessage = MessageBox.Show("Click 'Cancel' to kill the prior print job and print this one OR click 'OK' to finish the prior " + "print job and wait to re-click the Print button.", "Action Required", MessageBoxButton.OKCancel);
    
    if (myMessage == MessageBoxResult.Cancel)
    {
      // The user has opted to cancel the currently runnning 'synchronous geoprocessing task' PrintTask. 
      
      // Kill the PrintTask.
      _PrintTask.CancelAsync();
      
      // Clear out the status informational messages. 
      ListBox_StatusInformation.Items.Clear();
      
      // Create a UserToken to identify which PrintTask is running.
      string myToken = "MY TOKEN2";
      
      // Use the 'synchronous geoprocessing task' PrintTask.ExecuteAsync Method.
      _PrintTask.ExecuteAsync(myPrintParameters, myToken);
      
      // Update the status informational messages.
      ListBox_StatusInformation.Items.Add("The PrintTask was started.");
    }
    else if (myMessage == MessageBoxResult.OK)
    {
      // The user has opted to let the currently runnning 'synchronous geoprocessing task' PrintTask complete. 
      
      // Update the status informational messages.
      ListBox_StatusInformation.Items.Add("The PrintTask is busy (still processing).");
    }
  }
  else if (_PrintTask.IsBusy == false)
  {
    // There is not and existing 'synchronous geoprocessing task' PrintTask running.
    
    // Clear out the status informational messages. 
    ListBox_StatusInformation.Items.Clear();
    
    // Create a UserToken to identify which PrintTask is running.
    string myToken = "MY TOKEN";
    
    // Use the 'synchronous geoprocessing task' PrintTask.ExecuteAsync Method.
    _PrintTask.ExecuteAsync(myPrintParameters, myToken);
    
    // Enable button for the user to cancel the PrintTask request.
    Button_CancelAsync.IsEnabled = true;
    
    // Update the status informational messages.
    ListBox_StatusInformation.Items.Add("The PrintTask was started.");
  }
}
            
private void printTask_ExecuteCompleted(object sender, ESRI.ArcGIS.Client.Printing.PrintEventArgs e)
{
  // Use only for ExecuteAsync operations (i.e. synchronous geoprocessing tasks).
  
  // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  // PrintTask.ClientCertificate error checking:
  //
  // Get any error information (add your own enhancements if desired). 
  // You want to have this error information displayed to the user especially since a PKI secure service is being used 
  // for the PrintTask.
  System.Exception mySystemException = e.Error;
  if (mySystemException != null)
  {
    MessageBox.Show(mySystemException.ToString());
  }
  // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  
  // Get the PrintResult from the completed operation.
  ESRI.ArcGIS.Client.Printing.PrintResult myPrintResult = e.PrintResult;
  
  // Test is we have valid return PrintResults.
  if (myPrintResult != null)
  {
    // Get any messages returned from ArcGIS Server (add your own enhancements if desired).
    List<ESRI.ArcGIS.Client.Tasks.GPMessage> myListOfGPMessage = myPrintResult.Messages;
    
    // This is the userToken Parameter of the ExecuteAsync(printParameters,userToken)
    object myUserState = e.UserState;
    
    // Update the status informational messages.
    ListBox_StatusInformation.Items.Add("The PrintTask was completed for: " + myUserState.ToString());
    
    // Get the location of the image/.pdf created by ArcGIS Server.
    System.Uri myUri = myPrintResult.Url;
    
    // Open a new internet browser window with the generated image from the PrintTask.
    // NOTE: It is at this point that the second dialog appears asking for credentials so that the 
    // secured PrintTask content can be displayed in the WebBrowser.
    WebBrowser1.Navigate(myUri);
  }
}
            
private void Button_CancelAsync_Click(object sender, System.Windows.RoutedEventArgs e)
{
  // This will cancel the ExecuteAsync operation. 
  _PrintTask.CancelAsync();
  
  // Update the status informational messages.
  ListBox_StatusInformation.Items.Add("The PrintTask was canceled.");
}
VB.NETCopy Code
' Create a Global (aka. Member) variable for the PrintTask object that will be used in other 
' parts of the application.
Private _PrintTask As ESRI.ArcGIS.Client.Printing.PrintTask
            
' +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' PrintTask.ClientCertificate code:
'
' Global (i.e. Member) variable for the certificate.
Public _TheClientCertificate As New System.Security.Cryptography.X509Certificates.X509Certificate
' +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            
Public Sub New()
            
  InitializeComponent()
  
  ' +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  ' PrintTask.ClientCertificate code:
  '
  ' TODO: Provide a valid PrintTask.Url for a "synchronous geoprocessing task". It will be a secured ArcGIS Server that
  ' takes advantage of PKI security (i.e. https://).
  TextBox_Url.Text = "https://www.yoursite.com/arcgis/rest/services/Utilities/PrintingTools/GPServer/Export20Web20Map%20Task"
  ' +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  
  ' Set the _PrintTask variable to a new instance of the PrintTask Class.
  _PrintTask = New ESRI.ArcGIS.Client.Printing.PrintTask()
  
  ' Prevent the internet browser from using a cache for the PrintTask operations.
  _PrintTask.DisableClientCaching = True
  
  ' Set the PrintTask.Url from what is entered in the TextBox.
  _PrintTask.Url = TextBox_Url.Text
  
  ' Wire up an Event Handler for the PrintTask.ExecuteCompleted Event.
  AddHandler _PrintTask.ExecuteCompleted, AddressOf printTask_ExecuteCompleted
  
End Sub
  
Private Sub Button_ExecuteAsync_Click(sender As System.Object, e As System.Windows.RoutedEventArgs)
  
  ' +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  ' PrintTask.ClientCertificate code:
  '
  ' Create a new instance of a X509Store object (which is a physical store where certificates are persisted and managed).
  ' The X509Store object uses a StoreName based upon a 'personal certificate' and a StoreLocation for the user that 
  ' is currently logged in. The X509Store is accessed as ReadOnly to obtain the certificate. 
  ' NOTE: Don't forget to add a Reference to the System.Security Assembly. 
  Dim theX509Store As Security.Cryptography.X509Certificates.X509Store
  Dim theStoreName As Security.Cryptography.X509Certificates.StoreName = Security.Cryptography.X509Certificates.StoreName.My
  Dim theStoreLocation As Security.Cryptography.X509Certificates.StoreLocation = Security.Cryptography.X509Certificates.StoreLocation.CurrentUser
  theX509Store = New Security.Cryptography.X509Certificates.X509Store(theStoreName, theStoreLocation)
  theX509Store.Open(Security.Cryptography.X509Certificates.OpenFlags.ReadOnly)
  
  ' Obtain the collection of certificates in the X509Store. Note: depending on your organization there may multiple certificates!
  Dim certificates As Security.Cryptography.X509Certificates.X509Certificate2Collection = theX509Store.Certificates
  
  ' Display a dialog that prompts the user to select the correct certificate from the list of certificates available in the X509Store.
  ' If the correct certificate is chosen and the user clicks the button to execute the secured PrintTask it should
  ' display the results in the WebBrowser control. If a wrong certificate is chosen and then user then clicks the button to load the 
  ' secured PrintTask, the PrintTask.ExecuteComplete event will fire and display an error message with text similar to the 
  ' following: "The remote server returned an error: (403) Forbidden." or "The remote server returned error: (401) Unauthorized."
  ' NOTE: There will actually be 2 dialogs that appear asking for certificate credentials. The first dialog is the one that is
  ' invoked as a result of the X509Certificate2UI.SelectFromCollection() call. The second dialog automatically appears as a result
  ' of adding content into the WebBrowser.
  Dim theTitle As String = "Select a certificate"
  Dim theMessage As String = "Select the certificate to use for authentication to access the secured PrintTask."
  Dim theSelectionFlag As Security.Cryptography.X509Certificates.X509SelectionFlag = Security.Cryptography.X509Certificates.X509SelectionFlag.SingleSelection
  certificates = Security.Cryptography.X509Certificates.X509Certificate2UI.SelectFromCollection(certificates, theTitle, theMessage, theSelectionFlag)
  
  ' Only continue if at least one certificate is chosen.
  If certificates.Count > 0 Then
  
  ' Set the X509Certificate global variable. This will be used in constructing the PrintTask. 
  _TheClientCertificate = certificates(0)
  
  ' Set the PrintTask.ClientCertificate to enable printing from the secured web service. 
  _PrintTask.ClientCertificate = _TheClientCertificate
  End If
  ' +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  
  ' Define the settings for rendering the image/.pdf on the ArcGIS Server.
  
  ' Define the ExportOptions.
  Dim myExportOptions As New ESRI.ArcGIS.Client.Printing.ExportOptions
  myExportOptions.Dpi = 96 '96 DPI is typical Window OS setting.
  myExportOptions.OutputSize = New Size(MyMap.ActualWidth, MyMap.ActualHeight) ' Use the dimensions of the Map
  
  ' Define the PrintParameters.
  Dim myPrintParameters As New ESRI.ArcGIS.Client.Printing.PrintParameters(MyMap)
  myPrintParameters.ExportOptions = myExportOptions ' Use the ExportOptions defined earlier.
  myPrintParameters.LayoutTemplate = "MAP_ONLY" ' Look to the REST service to see what layout templates are supported.
  myPrintParameters.Format = "JPG" ' Look to the REST service to see what image formats are supported.
  
  ' NOTE: 
  ' If you try to submit more that one 'synchronous geoprocessing task' via PrintTask.ExecuteAsync at a time 
  ' using the ExecuteAsync methadology you will get a Visual Studio (Runtime) error: 
  ' NotSupportedException was unhandled by user code. "Task does not support concurrent  I/O operations. Cancel 
  ' the pending request or wait for it to complete." 
  ' In order to overcome this, use the PrintTask.IsBusy Property and take action accordingly.
  
  If _PrintTask.IsBusy = True Then
  
    ' There is an existing 'synchronous geoprocessing task' PrintTask running. 
    
    ' Use a simple MessageBox to get user direction on whether to stay with the currently running 'synchronous 
    ' geoprocessing task' PrintTask or cancel it and start another one.
    Dim myMessage As System.Windows.MessageBoxResult =
    MessageBox.Show("Click 'Cancel' to kill the prior print job and print this one OR click 'OK' to finish the prior " +
                    "print job and wait to re-click the Print button.", "Action Required", MessageBoxButton.OKCancel)
  
    If myMessage = MessageBoxResult.Cancel Then
      
      ' The user has opted to cancel the currently runnning 'synchronous geoprocessing task' PrintTask. 
      
      ' Kill the PrintTask.
      _PrintTask.CancelAsync()
      
      ' Clear out the status informational messages. 
      ListBox_StatusInformation.Items.Clear()
      
      ' Create a UserToken to identify which PrintTask is running.
      Dim myToken As String = "MY TOKEN2"
      
      ' Use the 'synchronous geoprocessing task' PrintTask.ExecuteAsync Method.
      _PrintTask.ExecuteAsync(myPrintParameters, myToken)
      
      ' Update the status informational messages.
      ListBox_StatusInformation.Items.Add("The PrintTask was started.")
      
    ElseIf myMessage = MessageBoxResult.OK Then
      
      ' The user has opted to let the currently runnning 'synchronous geoprocessing task' PrintTask complete. 
      
      ' Update the status informational messages.
      ListBox_StatusInformation.Items.Add("The PrintTask is busy (still processing).")
      
    End If
    
  ElseIf _PrintTask.IsBusy = False Then
  
    ' There is not and existing 'synchronous geoprocessing task' PrintTask running.
    
    ' Clear out the status informational messages. 
    ListBox_StatusInformation.Items.Clear()
    
    ' Create a UserToken to identify which PrintTask is running.
    Dim myToken As String = "MY TOKEN"
    
    ' Use the 'synchronous geoprocessing task' PrintTask.ExecuteAsync Method.
    _PrintTask.ExecuteAsync(myPrintParameters, myToken)
    
    ' Enable button for the user to cancel the PrintTask request.
    Button_CancelAsync.IsEnabled = True
    
     Update the status informational messages.
    ListBox_StatusInformation.Items.Add("The PrintTask was started.")
    
  End If
  
End Sub
  
Private Sub printTask_ExecuteCompleted(sender As Object, e As ESRI.ArcGIS.Client.Printing.PrintEventArgs)
  
  ' Use only for ExecuteAsync operations (i.e. synchronous geoprocessing tasks).
  
  ' +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  ' PrintTask.ClientCertificate error checking:
  '
  ' Get any error information (add your own enhancements if desired). 
  ' You want to have this error information displayed to the user especially since a PKI secure service is being used 
  ' for the PrintTask.
  Dim mySystemException As System.Exception = e.Error
  If mySystemException IsNot Nothing Then
    MessageBox.Show(mySystemException.ToString)
  End If
  ' +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  
  ' Get the PrintResult from the completed operation.
  Dim myPrintResult As ESRI.ArcGIS.Client.Printing.PrintResult = e.PrintResult
  
  ' Test is we have valid return PrintResults.
  If myPrintResult IsNot Nothing Then
    
    ' Get any messages returned from ArcGIS Server (add your own enhancements if desired).
    Dim myListOfGPMessage As List(Of ESRI.ArcGIS.Client.Tasks.GPMessage) = myPrintResult.Messages
    
    ' This is the userToken Parameter of the ExecuteAsync(printParameters,userToken)
    Dim myUserState As Object = e.UserState
    
    ' Update the status informational messages.
    ListBox_StatusInformation.Items.Add("The PrintTask was completed for: " + myUserState)
    
    ' Get the location of the image/.pdf created by ArcGIS Server.
    Dim myUri As System.Uri = myPrintResult.Url
    
    ' Open a new internet browser window with the generated image from the PrintTask.
    ' NOTE: It is at this point that the second dialog appears asking for credentials so that the 
    ' secured PrintTask content can be displayed in the WebBrowser.
    WebBrowser1.Navigate(myUri)
    
  End If
  
End Sub
  
Private Sub Button_CancelAsync_Click(sender As System.Object, e As System.Windows.RoutedEventArgs)
  
  ' This will cancel the ExecuteAsync operation. 
  _PrintTask.CancelAsync()
  
  ' Update the status informational messages.
  ListBox_StatusInformation.Items.Add("The PrintTask was canceled.")
  
End Sub

Requirements

Target Platforms: Windows XP Professional, Windows Server 2003 family, Windows Vista, Windows Server 2008 family, Windows 7, Windows 8

See Also

© ESRI, Inc. All Rights Reserved.