- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
In my previous article we enhanced the C#/.NET webservice example on the wiki using Visual Studio Community 2015. I introduced some key concepts like WPF instead of Windows Forms, and using the App.config file to contain your userid and password. Additionally I changed it up a bit and gave an example of a get instead of an insert. This included how to receive the information coming back from ServiceNow, and make use of it. Finally, I added in a sprinkling of best and good practices.
Wiki article: Web Services C Sharp .NET End to End Tutorial
My article: Mini-Lab: Visual Studio Community 2015 and the C# Web Service Example
In this article we will continue with this example. I will be showing how to expand the code and UI to incorporate the recommended best practices from the first part of another Wiki article:
Retrieving A Large Number Of Records Using SOAP - ServiceNow Wiki
Specifically section 2.1 and 2.1.3: Using Filters to Limit the Number of Results.
Well...I will be demonstrating the how, but not exactly like it is described. I will leave that for you to do!
NOTE: I highly recommend performing both labs in my previous article before continuing with the lab in this article.
Steps:
1. If you haven't already; you will need to install VS Community 2015. See my previous article for the links to download and the how-to.
2. Create a new VS WPF Project.
3. Test.
Lab 2.1: Creating the ServiceNow Filter Limiter Project
1. Read through section 2.1 of the ServiceNow Wiki article. This shows three approaches for limiting the number of records being retrieved. We will be focusing on the third: Best Practice.
2. In the VS IDE navigate to File -> New -> Project. The new project form will be displayed.
3. Fill in the form with the following:
a. Choose: WPF Application
b. Name: ServiceNowFilterLimiter
c. Click on the OK button to create your project.
4. A new blank WPF project will be created.
5. From the Toolbox tab on the left pull out the following controls:
a. RichTextbox control and a button control onto your new form. You will find the RichTextbox control under the All WPF Controls tree.
b. Five Labels
c. Five Combo Box controls
d. One button control
e. Arrange them to look something like this (yeah I played with the color on the rtb control):
f. Change the text of the labels, checkbox and button to be that as you see on the image above.
g. Change the names of the controls to the following:
i. RichTextBox: rtbResults
ii. Button: btnSendQuery
iii. Checkbox: chkActive
iv. Impact Combo: cmbImpact
v. Urgency Combo: cmbUrgency
vi. Priority Combo: cmbPriority
vii. State Combo: cmbState
viii. User Combo: cmbUser
NOTE: It is also a good practice to change the names on your labels as well.
h. This is probably a good point to save everything. Navigate to File -> Save All.
6. Now right-click on the ServiceNowFilterLimiter project to bring up the project context menu.
7. Navigate to Add -> Service Reference. This will bring up the Add Service Reference Form.
8. Fill in the form with the following:
a. Address: https://<<servicenow instance name>>.service-now.com?incident.do?wsdl
b. Namespace: incidentTable
9. Click the Go button. A popup will ask you to fill in the userid and password. BEWARE: It will send these in cleartext to ServiceNow. Don't give that user too much authority. Read should be sufficient. We will be adding security next.
10. After a proper connection has been made the Add Service Reference form should look like this:
11. Click the OK button. A new Service Reference will be added to the project.
12. In the solution Explorer double-click on the App.config entry. This will display the App.config file in the editor. We will be adding some security, and the uid/pw data.
a. Replace the the following XML to the <Security mode=... /> line with the following code:
<security mode="Transport">
<transport clientCredentialType="Basic" proxyCredentialType="Basic" realm="">
<extendedProtectionPolicy policyEnforcement="Never" />
</transport>
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
b. Add in a new section at the bottom after the </system_serviceModel> tag. I used my uid/pw combo that I created in a previousarticle. BTW, this is a best practice! Never hard-code this stuff in your code!
<appSettings>
<add key="userID" value="svcuser" />
<add key="password" value="Pragmat1$t10"/>
</appSettings>
NOTE: If you REALLY want to crank down on the security of this file I found the following article excellent reading:
Jon Galloway - Encrypting Passwords in a .NET app.config File
c. Save the file (ctl-s). The file should look something like this:
13. Next we will add the Configuration reference to our project. This is not (and in my book should be) done for you automatically.
a. Right-click on the References section in the Solution Explorer, and choose Add Reference from the context pop-up. This will display the Add Reference form.
b. Scroll down and find the System.Configuration entry. Click on this; a check box will be displayed. Make sure this is checked.
c. Click OK to save your work.
14. Right-Click again on the ServiceNowFilterLimiter project to bring up the project context menu.
15. Navigate to Add -> New Item. This will bring up the New Item Form. We will be adding a class that will be used as an object to contain our listed items in each combo box.
a. Choose Class, and make the name ComboBoxItem.cs
b. Click on the Add button. This will display an empty class form.
c. Replace all the code on the form with the following:
namespace ServiceNowFilterLimiter
{
public class ComboBoxItem
{
public string Value = "";
public string Text = "";
public ComboBoxItem(string val, string text)
{
Value = val;
Text = text;
}
public override string ToString()
{
return Text;
}
}
}
16. Now we will be adding in the core code that will do the work.
a. Double-click on the Send Command button. This will bring up the MainWindow code file. You can also do this from the Solution Explorer.
b. Replace both the MainWindow() and btnSend_Click() methods with the following code:
NOTE: I have added in comments to clarify what the code does.
Best Practice: Add #region tags into your C# code to help organize sections that are related. This also helps you "minimize" sections of code to help manage large code files.
public MainWindow()
{
InitializeComponent();
initializeCombos();
initializeResults();
chkActive.SetCurrentValue(CheckBox.IsCheckedProperty, true); // default active to checked
}
private void btnSendQuery_Click(object sender, RoutedEventArgs e)
{
// Clear out our results (otherwise each query would tack onto the next)
rtbResults.Document.Blocks.Clear();
// declare our soap object for transmission
incidentTable.ServiceNowSoapClient soapClient = new incidentTable.ServiceNowSoapClient();
// pull the cred info from the app.config
soapClient.ClientCredentials.UserName.UserName = ConfigurationManager.AppSettings["userID"];
soapClient.ClientCredentials.UserName.Password = ConfigurationManager.AppSettings["password"];
// Initialize our query
incidentTable.getRecords getRecordsQuery = new incidentTable.getRecords();
// Initialize our response. And since we don't know how many will be returned put it into a List object
List<incidentTable.getRecordsResponseGetRecordsResult> responseList = new List<incidentTable.getRecordsResponseGetRecordsResult>();
// Activate query components based on what was chosen by the user in the UI
getRecordsQuery.assigned_to = cmbUser.SelectedValue != null && ((ComboBoxItem)cmbUser.SelectedValue).Value != "" ? ((ComboBoxItem)cmbUser.SelectedValue).Value : null;
getRecordsQuery.state = cmbState.SelectedValue != null && ((ComboBoxItem)cmbState.SelectedValue).Value != "" ? ((ComboBoxItem)cmbState.SelectedValue).Value : null;
getRecordsQuery.priority = cmbPriority.SelectedValue != null && ((ComboBoxItem)cmbPriority.SelectedValue).Value != "" ? ((ComboBoxItem)cmbPriority.SelectedValue).Value : null;
getRecordsQuery.urgency = cmbUrgency.SelectedValue != null && ((ComboBoxItem)cmbUrgency.SelectedValue).Value != "" ? ((ComboBoxItem)cmbUrgency.SelectedValue).Value : null;
getRecordsQuery.impact = cmbImpact.SelectedValue != null && ((ComboBoxItem)cmbImpact.SelectedValue).Value != "" ? ((ComboBoxItem)cmbImpact.SelectedValue).Value : null;
try
{
// Now fire off our query. Use a LINQ command to Order the results
responseList = soapClient.getRecords(getRecordsQuery).OrderBy(o => o.number).ToList();
// use a StringBuilder so that we can take advantage of the built-in formatter
StringBuilder results = new StringBuilder();
results.AppendFormat("Total records found: {0}", responseList.Count);
// Loop through our response records and print them to the results window
foreach (incidentTable.getRecordsResponseGetRecordsResult response in responseList)
{
results.AppendFormat("\n{0}\t{1}\t{2}",
response.number,
response.severity,
response.short_description.TrimEnd());
}
// Post the results for display
rtbResults.AppendText(results.ToString());
}
catch (Exception error)
{
// something bad happened!
rtbResults.AppendText(error.Message);
}
}
#region Initializers
/// <summary>
/// Method for initializing all of the Combo boxes on the form.
/// </summary>
private void initializeCombos()
{
// allow only values from the checkbox lists
cmbImpact.IsEditable = false;
cmbPriority.IsEditable = false;
cmbUrgency.IsEditable = false;
cmbState.IsEditable = false;
cmbImpact.Items.Clear();
cmbImpact.Items.Add(new ComboBoxItem("", ""));
cmbImpact.Items.Add(new ComboBoxItem("1", "High"));
cmbImpact.Items.Add(new ComboBoxItem("2", "Medium"));
cmbImpact.Items.Add(new ComboBoxItem("3", "Low"));
cmbPriority.Items.Clear();
cmbPriority.Items.Add(new ComboBoxItem("", ""));
cmbPriority.Items.Add(new ComboBoxItem("1", "High"));
cmbPriority.Items.Add(new ComboBoxItem("2", "Medium"));
cmbPriority.Items.Add(new ComboBoxItem("3", "Low"));
cmbUrgency.Items.Clear();
cmbUrgency.Items.Add(new ComboBoxItem("", ""));
cmbUrgency.Items.Add(new ComboBoxItem("1", "Critical"));
cmbUrgency.Items.Add(new ComboBoxItem("2", "High"));
cmbUrgency.Items.Add(new ComboBoxItem("3", "Medium"));
cmbUrgency.Items.Add(new ComboBoxItem("4", "Low"));
cmbUrgency.Items.Add(new ComboBoxItem("5", "Planning"));
cmbState.Items.Clear();
cmbState.Items.Add(new ComboBoxItem("", ""));
cmbState.Items.Add(new ComboBoxItem("1", "New"));
cmbState.Items.Add(new ComboBoxItem("2", "Active"));
cmbState.Items.Add(new ComboBoxItem("3", "Awaiting Problem"));
cmbState.Items.Add(new ComboBoxItem("4", "Awaiting User Info"));
cmbState.Items.Add(new ComboBoxItem("5", "Awaiting Evidence"));
cmbState.Items.Add(new ComboBoxItem("6", "Resolved"));
cmbState.Items.Add(new ComboBoxItem("7", "Closed"));
cmbUser.Items.Clear();
cmbUser.Items.Add(new ComboBoxItem("", ""));
cmbUser.Items.Add(new ComboBoxItem("46d44a23a9fe19810012d100cca80666", "Beth Anglin"));
}
/// <summary>
/// Method for setting up the results box at program load.
/// </summary>
private void initializeResults()
{
// clear out the rich text box
rtbResults.Document.Blocks.Clear();
// make the scrollbar to be visible if results larger than display
rtbResults.VerticalScrollBarVisibility = ScrollBarVisibility.Auto;
// kill the pesky extra new lines style
Style noSpaceStyle = new Style(typeof(Paragraph));
noSpaceStyle.Setters.Add(new Setter(Paragraph.MarginProperty, new Thickness(0)));
rtbResults.Resources.Add(typeof(Paragraph), noSpaceStyle);
}
#endregion
17. We are ready to test! Navigate to Debug -> Start Debugging. This will run our application and display the form.
a. Impact: High
b. State: Active
c. Make sure Active is checked (should be defaulted according to the code right?!)
d. User: Beth Anglin
e. The results should appear in the window on the form.
18. Click on the Send Command button. My results looked like this:
NOTE: If you get nothing back then go over to your instance and see if there are any records you can retrieve using the above settings.
19. Finally always clean up your unused Usings (another best practice)! See my previous article on how to do this.
That's it! You have now implemented a more complex form for limiting the results to be returned from ServiceNow! Cool, huh?! 😄
Steven Bell
If you find this article helps you, don't forget to log in and "like" it!
Also, if you are not already, I would like to encourage you to become a member of our blog!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
