Created
March 23, 2011 00:04
-
-
Save buzzedword/882368 to your computer and use it in GitHub Desktop.
Zendesk REST Wrapper
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using System.Net; | |
using System.IO; | |
namespace MyApplication | |
{ | |
/// <summary> | |
/// This class is a simple authentication/ticket submission program for ZenDesk. | |
/// </summary> | |
class ZenRequest | |
{ | |
/// <summary> | |
/// AppConfigFileSettings is class that reads/updates the App.Config file for | |
/// simple transport of data. You should use more secure means to pass user sessions, | |
/// this was necessary in my desktop app for GPO purposes. | |
/// </summary> | |
AppConfigFileSettings reg = new AppConfigFileSettings(); | |
/// <summary> | |
/// ZenRequest is our constructor, and for security purposes, we do not allow null at | |
/// build time. | |
/// </summary> | |
/// <param name="userName">Agent or Admin with all ticket access</param> | |
/// <param name="password">In cleartext. This is a lament's example-- please secure your code!</param> | |
/// <param name="debug">Are you using the sandbox URL, or the production?</param> | |
public ZenRequest(String userName, String password, Boolean debug) | |
{ | |
if (debug == true) | |
{ | |
zenURL = "<sandbox_url>"; // Replace this string with the URL of your sandbox to test the app. | |
} | |
else if (debug == false) | |
{ | |
zenURL = "<production_url>"; // Replace this string with the URL of your production helpdesk. | |
} | |
zenUserName = userName; | |
zenPassword = password; | |
} | |
/// <summary> | |
/// ZenAuth is a general authentication call for your application. This is essentially your | |
/// "application login", and should be executed once before any commands are posted against the | |
/// ZenDesk API to speed up the initial call. | |
/// | |
/// Remember, your user account must have "all ticket" access for this to work. This is the best | |
/// method I've found for authenticating a user against ZenDesk. | |
/// </summary> | |
/// <returns> | |
/// On a successful connection, return the ZenDesk Status code. You must handle the status | |
/// outside of this class. | |
/// | |
/// Note: It is possible to get a Status response that does NOT authenticate you, make sure you stay | |
/// current with the ZenDesk REST API. | |
/// </returns> | |
public string ZenAuth() | |
{ | |
WebClient zenWeb = zenClient(); // See zenClient below for further description. | |
// The next two lines formulate a GET request using the URL we specified at object creation | |
// as well as the "users.xml" file we use for simple authentication. | |
String zenFile = "users.xml"; | |
String zenRequest = zenURL + zenFile; | |
// This gracefully executes a GET request, and will degrade without an application crash. | |
try | |
{ | |
zenWeb.DownloadData(zenRequest); // Start the GET request. | |
return zenWeb.ResponseHeaders["Status"]; // Returns your status code. You want to be | |
// Checking for a 200 OK. | |
} | |
catch (Exception e) | |
{ | |
return "Error"; // Self explanatory. Handle your error properly. | |
} | |
} | |
/// <summary> | |
/// This method performs two functions: the first is to create a new ticket, using an XML-structured POST. | |
/// The second function is to return the ticket number for application usage. | |
/// </summary> | |
/// <param name="userName">This is the email you will be creating a ticket for.</param> | |
/// <param name="displayName">How do you want to display the name in ZenDesk?</param> | |
/// <returns>Status Code for action.</returns> | |
public String ZenSubmit(String userName, String displayName) | |
{ | |
WebClient zenWeb = zenClient(); // See zenClient below for more information. | |
// The following lines structure a POST request against tickets.xml. I've also accounted | |
// for an additional custom ticket field you may have in your helpdesk. | |
String zenFile = "tickets.xml"; | |
String zenRequest = zenURL + zenFile; | |
String customTicketField = ""; | |
// Remember, "reg" is reading from my app.config-- I strongly recommend using another | |
// method to store your user session. | |
if (reg.ReturnAppSettings("userName") == "<specificUser1>") // Check for specific user | |
// Enter user specific custom field. | |
{ | |
customTicketField = @"<ticket-field-entry> | |
<ticket-field-id>[ID for custom ticket field.]</ticket-field-id> | |
<value>[tag for custom ticket field]</value> | |
</ticket-field-entry>"; | |
} | |
else if (reg.ReturnAppSettings("userName") == "<specificUser2>") // See above. | |
{ | |
customTicketField = @"<ticket-field-entry> | |
<ticket-field-id>[ID for custom ticket field.]</ticket-field-id> | |
<value>[tag for custom ticket field]</value> | |
</ticket-field-entry>"; | |
} | |
else | |
{ | |
customTicketField = ""; // Do not enter custom field. | |
} | |
// The String Literal below constructs the XML needed for a successful POST, based on the | |
// fields we've already populated above. | |
String createTicketXML = @"<ticket> | |
<subject>[Ticket Subject]</subject> | |
<description>[Body of ticket]</description> | |
<requester-name>" + displayName + @"</requester-name> | |
<requester-email>" + userName + @"</requester-email> | |
<set-tags>[tag to set, if any]</set-tags> | |
<ticket-field-entries type=""array""> | |
" + customTicketField + @" | |
</ticket-field-entries> | |
</ticket>"; | |
zenWeb.UploadString(zenRequest, createTicketXML); // Execute the POST request, and hopefully create ticket. | |
// If the ticket is created successfully, return the ticket number. | |
// Check the REST API frequently in case the location of the ticket changes. | |
if (zenWeb.ResponseHeaders["Status"] == "201 Created") | |
{ | |
zenTicketURL = zenWeb.ResponseHeaders["Location"]; // Returns the ticket location in XML. | |
// The ticket number is extracted by removing the URL we are using, followed by the tickets/ URI, | |
// and finally by stripping ".xml" from the remaining string. Again, all of these locations are | |
// documented in the REST API for ZenDesk. | |
int URLcount = CountChars(zenURL + "tickets/"); | |
String returnVar = zenTicketURL; | |
returnVar = returnVar.Remove(0, URLcount); | |
char[] xmlChar = { '.', 'x', 'm', 'l' }; | |
returnVar = returnVar.TrimEnd(xmlChar); | |
return returnVar; | |
} | |
else | |
{ | |
return "FAIL"; // Ticket creation unsuccessful. | |
} | |
} | |
/// <summary> | |
/// This is just an accessory method to get the last ticket created, should you ever need to. | |
/// </summary> | |
/// <returns>XML return of last ticket created.</returns> | |
public String getTicket() { | |
return zenTicketURL; | |
} | |
/// <summary> | |
/// This method is the most important one in the entire class. Instead of creating a WebClient for every single | |
/// action I had to take, I opted instead to set the basics up in zenClient, which can then be object referenced | |
/// with every new call, and extended. This also promises proper garbage collection from the program, disposing of | |
/// queries after they have been executed. | |
/// </summary> | |
/// <returns>Default settings for all WebClients</returns> | |
private WebClient zenClient() | |
{ | |
WebClient zenPrimaryClient = new WebClient(); // WebClient will provide transport for GET/POST commands. | |
zenPrimaryClient.Credentials = new System.Net.NetworkCredential(zenUserName, zenPassword); // Secures UserName and Password for usage. | |
zenPrimaryClient.Headers.Add("Content-Type", "application/xml"); // Set your MIME type. | |
zenPrimaryClient.BaseAddress = zenURL; // Set the Base URL for all commands. | |
return zenPrimaryClient; // Return all settings. | |
} | |
/// <summary> | |
/// Generic method to count all characters in a string, and account for all spaces. | |
/// Recommended for usage with URLs. | |
/// </summary> | |
/// <param name="value">URL to check</param> | |
/// <returns>Characters in String/URL</returns> | |
static int CountChars(string value) | |
{ | |
int result = 0; | |
bool lastWasSpace = false; | |
foreach (char c in value) | |
{ | |
if (char.IsWhiteSpace(c)) | |
{ | |
if (lastWasSpace == false) | |
{ | |
result++; | |
} | |
lastWasSpace = true; | |
} | |
else | |
{ | |
result++; | |
lastWasSpace = false; | |
} | |
} | |
return result; | |
} | |
#region Declarations | |
private String zenTicketURL; | |
private String zenUserName; | |
private String zenPassword; | |
private String zenURL; | |
#endregion | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment