The following example shows how to use the HttpClient in C#. This sample simply makes a call out to google.com and
displays the return html in the console window. This sample uses a wrapper class around the HttpClient object
in order to provide error checking, additional features, call backs, etc. Note that this class can be used in any project type
(ie Net, AspNetCore, etc.) Note too that this is a real world production class so...
Using the Class
The PFSHttp Wrapper for the HttpClient Class
Using the Class
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Net; namespace Samples { class Program { static void Main(string[] args) { Console.Title = "WebClient Sample"; Console.WriteLine(Console.Title); Console.WriteLine(); Console.WriteLine("***BEGIN SAMPLE OUTPUT***"); // define the new wrapper class PFSHttp h = new PFSHttp(); // set the target url h.Url = "http://www.google.com"; // perform a Get HttpStatusCode c1 = h.Get().Result; // get the response as a string string s = h.GetResponseAsString().Result; // write the string to the console window Console.WriteLine(s); // dispose of the wrapper class. h.Dispose(); Console.WriteLine("***END SAMPLE OUTPUT***"); Console.ReadKey(); } } } // END PROGRAM
The PFSHttp Wrapper for the HttpClient Class
#pragma warning disable IDE1005 #pragma warning disable IDE0032 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; using System.Net; using System.Net.Http; using System.Web; using System.Net.Http.Headers; using System.Xml; using System.Net.Mime; using System.Diagnostics; namespace Samples { public class PFSHttp: IDisposable { // header constants private const string HEADER_CONTENT_LENGTH = "Content-Length"; private const string HEADER_CONTENT_TYPE = "Content-Type"; // defaults for timeouts private const int DEFAULT_TIMEOUT_HOURS = 0; private const int DEFAULT_TIMEOUT_MINUTES = 2; private const int DEFAULT_TIMEOUT_SECONDS = 0; // response handler delegates. public delegate void HttpClientResponseHandler(PFSHttp objThis, object UserDataObject); public delegate void HttpClientTimeoutHandler(PFSHttp objThis, object UserDataObject); public delegate void HttpClientErrorHandler(PFSHttp objThis, object UserDataObject); // Headers private List> lstHeaders = new List >(); // list that holds headers private List > lstAcceptHeaders = new List >(); // accept headers private List > lstQueryParameters = new List >(); // This holds // local handlers (functions) private HttpClientResponseHandler dlgResponseHandler = null; private HttpClientTimeoutHandler dlgTimeoutHandler = null; private HttpClientErrorHandler dlgErrorHandler = null; // request object private HttpClient objHttpClient = null; // response object private HttpResponseMessage objHttpResponse = null; // User Data that is state persistent private object objUserData = new object(); // local class properties. private string strUrl = ""; private string strUserID = ""; private string strPassword = ""; private int intTimeoutHours = DEFAULT_TIMEOUT_HOURS; private int intTimeoutMinutes = DEFAULT_TIMEOUT_MINUTES; private int intTimeoutSeconds = DEFAULT_TIMEOUT_SECONDS; private string strID = ""; private int intExceptionCode = 0; private string strExceptionSource = ""; private string strExceptionMessage = ""; private bool boolExceptionFlag = false; // timespan variable private TimeSpan tsHttpTimeOut = new TimeSpan(DEFAULT_TIMEOUT_HOURS, DEFAULT_TIMEOUT_MINUTES, DEFAULT_TIMEOUT_SECONDS); // post bodys. private string strPostBody = ""; private string strXml = ""; private string strJson = ""; // Get the HttpClient object public HttpClient HttpRequest { get { return objHttpClient; } } // Get the Response Message object public HttpResponseMessage HttpResponse { get { return objHttpResponse; } } // Get the Status Code public HttpStatusCode StatusCode { get { HttpStatusCode rt = HttpStatusCode.BadRequest; if (objHttpResponse != null) { rt = objHttpResponse.StatusCode; } return rt; } } // Get the exception code. public int ExceptionCode { get { return intExceptionCode; } } // the exception source public string ExceptionSource { get { return strExceptionSource; } } // the exception message public string ExceptionMessage { get { return strExceptionMessage; } } // flag indicating whether exception occured public bool ExceptionFlag { get { return boolExceptionFlag; } } // stateful user data that will get public object UserData { get { return objUserData; } set { objUserData = value; } } // url. May or may not contain query parameters public string Url { get { return strUrl; } set { strUrl = value; } } // a string value user defined. public string ID { get { return strID; } set { strID = value; } } // function after response received. public HttpClientResponseHandler ResponseHandler { get { return dlgResponseHandler; } set { dlgResponseHandler = value; } } // function called if timeout occurs public HttpClientTimeoutHandler TimeoutHandler { get { return dlgTimeoutHandler; } set { dlgTimeoutHandler = value; } } // function called if error occurs public HttpClientErrorHandler ErrorHandler { get { return dlgErrorHandler; } set { dlgErrorHandler = value; } } // post body. manually set public string PostBody { get { return strPostBody; } set { strPostBody = value; } } // used for submitting xml only public string Xml { get { return strXml; } set { strXml = value; } } // used for submitting JSON public string Json { get { return strJson; } set { strJson = value; } } // user id public string UserID { get { return strUserID; } set { strUserID = value; } } // user password public string Password { get { return strPassword; } set { strPassword = value; } } // timeout hours public int TimeoutHours { get { return intTimeoutHours; } set { intTimeoutHours = value; } } // timeout minutes public int TimeoutMinutes { get { return intTimeoutMinutes; } set { intTimeoutMinutes = value; } } // timeout seconds public int TimeoutSeconds { get { return intTimeoutSeconds; } set { intTimeoutSeconds = value; } } // ------------------------------------------- // Adds a query or post parameter // ------------------------------------------- public void AddQueryParameter(string sKey, string sValue) { KeyValuePair kvp = new KeyValuePair (sKey, sValue); lstQueryParameters.Add(kvp); } // adds string query or post parameter public void aqp(string sKey, string sValue) { AddQueryParameter(sKey, sValue); } // adds datetime query or post parameter public void aqp(string sKey, DateTime dtValue) { string strDt = dtValue.ToString("yyyy-MM-ddTHH:mm:ss"); AddQueryParameter(sKey, strDt); } // adds int query or post parameter public void aqp(string sKey, int nValue) { AddQueryParameter(sKey, nValue.ToString()); } // adds double query or post parameter public void aqp(string sKey, double dValue) { AddQueryParameter(sKey, dValue.ToString()); } // adds long query or post parameter public void aqp(string sKey, long lValue) { AddQueryParameter(sKey, lValue.ToString()); } // adds float query or post parameter public void aqp(string sKey, float fVal) { AddQueryParameter(sKey, fVal.ToString()); } // adds decimal query or post parameter public void aqp(string sKey, decimal dValue) { AddQueryParameter(sKey, dValue.ToString()); } // adds byte query or post parameter public void aqp(string sKey, byte b) { aqp(sKey, (int)b); } // adds char query or post parameter public void aqp(string sKey, char c) { AddQueryParameter(sKey, c.ToString()); } // adds boolean query or post parameter public void aqp(string sKey, bool b) { int nval = 0; if (b) { nval = 1; } aqp(sKey, nval); } // ---------------------------------------------- // Adds a request header // ---------------------------------------------- public void AddHdr(string sKey, string sVal) { // only add if (string.Compare(sKey.ToLower(), HEADER_CONTENT_LENGTH.ToLower()) != 0) { KeyValuePair kvp = new KeyValuePair (sKey, sVal); lstHeaders.Add(kvp); } } // ----------------------------------------- // Adds an accept header // ----------------------------------------- public void AddAcceptHdr(string sKey) { KeyValuePair kvp = new KeyValuePair (sKey, ""); } public void AddAcceptHdr(string sKey, double dVal) { KeyValuePair kvp = new KeyValuePair (sKey, dVal.ToString()); } // ------------------------------------------------------------ // Gets the response as a string // ------------------------------------------------------------ public async Task GetResponseAsString() { string s = ""; if (objHttpResponse != null) { if (objHttpResponse.Content != null) { s = await objHttpResponse.Content.ReadAsStringAsync(); } } return s; } // ------------------------------------------------------------ // Gets response as a text reader // ------------------------------------------------------------ public async Task GetResponseAsTextReader() { TextReader tx = null; try { string s = await GetResponseAsString(); tx = new StringReader(s); } catch (Exception) { } return tx; } // ------------------------------------------------------------ // Gets response as a xml reader // ------------------------------------------------------------ public async Task GetResponseAsXmlReader() { XmlReader xr = null; try { TextReader tx = await GetResponseAsTextReader(); xr = XmlReader.Create(tx); } catch (Exception) { } return xr; } // --------------------------------------------------------- // Gets response as a stream // --------------------------------------------------------- public async Task GetResponseAsStream() { Stream fs = null; if (objHttpResponse != null) { if (objHttpResponse.Content != null) { try { Stream fss = await objHttpResponse.Content.ReadAsStreamAsync(); fs = fss; } catch (Exception) { } } } return fs; } // ----------------------------------------------------------- // Gets response as a byte array // ----------------------------------------------------------- public async Task GetResponseAsByteArray() { byte[] b = null; if (objHttpResponse != null) { if (objHttpResponse.Content != null) { try { b = await objHttpResponse.Content.ReadAsByteArrayAsync(); } catch (Exception) { } } } return b; } // -------------------------------------------------------------- // Does a get call. // -------------------------------------------------------------- public async Task Get() { HttpStatusCode rc = HttpStatusCode.BadRequest; objHttpResponse = new HttpResponseMessage(); // defines a new http client SetNewHttpClient(); // now build the url. string sUrl = strUrl; if (lstQueryParameters.Count > 0) { string sep = ""; sUrl = sUrl + "?"; for (int i = 0; i < lstQueryParameters.Count; i++) { string tmp = sep + lstQueryParameters[i].Key + "=" + WebUtility.UrlEncode(lstQueryParameters[i].Value); sUrl += tmp; sep = "&"; } } // add the headers AddHeaders(); // do the get request try { // wait the whole time objHttpResponse = await objHttpClient.GetAsync(sUrl, HttpCompletionOption.ResponseContentRead); // capture the status code rc = objHttpResponse.StatusCode; // if the response is a timeout, then if the handler is defined, do the timeout handler, otherwise // try and do the regular response handler if (rc == HttpStatusCode.RequestTimeout || rc == HttpStatusCode.GatewayTimeout) { if (dlgTimeoutHandler != null) { dlgTimeoutHandler(this, objUserData); } else if (dlgResponseHandler != null) { dlgResponseHandler(this, objUserData); } } // if not a timeout handler, then if the response handler is defined, // do that. else { if (dlgResponseHandler != null) { dlgResponseHandler(this, objUserData); } } } // exception occurred catch (Exception ex) { boolExceptionFlag = true; intExceptionCode = ex.HResult; strExceptionSource = ex.Source; strExceptionMessage = ex.Message; if (dlgErrorHandler != null) { dlgErrorHandler(this, objUserData); } else if (dlgResponseHandler != null) { dlgResponseHandler(this, objUserData); } } return rc; } // ----------------------------------------------- // does a post call // ----------------------------------------------- public async Task Post() { HttpStatusCode rc = HttpStatusCode.BadRequest; int nContentLength = 0; // this is the post content HttpContent uCont; // defines a new http client SetNewHttpClient(); // now we need to either post the query parameters, the preset post data, or the xml. if (strXml.Length == 0) { if (strJson.Length == 0) { // if the post body is blank, then try and set via // any query parameters. if (PostBody.Length == 0) { string sep = ""; for (int i = 0; i < lstQueryParameters.Count; i++) { KeyValuePair kvp = lstQueryParameters[i]; strPostBody += sep + kvp.Key + "=" + WebUtility.UrlEncode(kvp.Value); sep = "&"; } uCont = new StringContent(strPostBody); } else { uCont = new StringContent(strPostBody); } nContentLength = strPostBody.Length; } else { nContentLength = strJson.Length; uCont = new StringContent(strJson); } } else { nContentLength = strXml.Length; uCont = new StringContent(strXml); } // always add the content length objHttpClient.DefaultRequestHeaders.Add(HEADER_CONTENT_LENGTH, nContentLength.ToString()); // add the rest of the headers AddHeaders(); // get the response. try { // post the content. wait for response objHttpResponse = await objHttpClient.PostAsync(Url, uCont); // get the status code rc = objHttpResponse.StatusCode; // if the response is a timeout, then if the handler is defined, do the timeout handler, otherwise // try and do the regular response handler if (rc == HttpStatusCode.RequestTimeout || rc == HttpStatusCode.GatewayTimeout) { if (dlgTimeoutHandler != null) { dlgTimeoutHandler(this, objUserData); } else if (dlgResponseHandler != null) { dlgResponseHandler(this, objUserData); } } // if not a timeout handler, then if the response handler is defined, // do that. else { if (dlgResponseHandler != null) { dlgResponseHandler(this, objUserData); } } } // exception occured. catch(Exception ex) { boolExceptionFlag = true; intExceptionCode = ex.HResult; strExceptionSource = ex.Source; strExceptionMessage = ex.Message; if (dlgErrorHandler != null) { dlgErrorHandler(this, objUserData); } else if (dlgResponseHandler != null) { dlgResponseHandler(this, objUserData); } } return rc; } // ----------------------------------------------------------- // Sets a new HttpClient // ----------------------------------------------------------- private void SetNewHttpClient() { // if the user id is specified, then we // need to specify a user id and passsword if (strUserID.Length > 0) { HttpClientHandler cliHandler = new HttpClientHandler(); cliHandler.Credentials = new NetworkCredential(strUserID, strPassword); objHttpClient = new HttpClient(cliHandler); } else { objHttpClient = new HttpClient(); } // set the client timeout objHttpClient.Timeout = new TimeSpan(intTimeoutHours, intTimeoutMinutes, intTimeoutSeconds); } // -------------------------------------------------------- // This adds the request and accept headers to the client // -------------------------------------------------------- private void AddHeaders() { // add the headers except for content type and content length for (int i = 0; i < lstHeaders.Count; i++) { KeyValuePair kvp = lstHeaders[i]; objHttpClient.DefaultRequestHeaders.Add(kvp.Key, kvp.Value); } // add the accept headers for (int i = 0; i < lstAcceptHeaders.Count; i++) { MediaTypeWithQualityHeaderValue mtyp = null; KeyValuePair kvp = lstAcceptHeaders[i]; if (kvp.Value.Length > 0) { mtyp = new MediaTypeWithQualityHeaderValue(kvp.Key, Convert.ToDouble(kvp.Value)); } else { mtyp = new MediaTypeWithQualityHeaderValue(kvp.Key); } objHttpClient.DefaultRequestHeaders.Accept.Add(mtyp); } } // ---------------------------------------------------- // Dispose of everything // ---------------------------------------------------- protected virtual void Dispose(bool disposing) { if (disposing) { objHttpResponse.Dispose(); objHttpClient.Dispose(); dlgResponseHandler = null; dlgErrorHandler = null; dlgTimeoutHandler = null; objUserData = null; } } // ----------------------------------------------------- // Disposing // ----------------------------------------------------- public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } // ---------------------------------------------------------------- // Convenience Routines // ---------------------------------------------------------------- // form submit. public void AddDefaultPostHeaders() { AddHdr(HEADER_CONTENT_TYPE, "application/x-www-form-urlencoded"); } // convenience for xml posts public void AddDefaultXmlPostHeaders() { AddHdr(HEADER_CONTENT_TYPE, "text/xml"); } // convenience for json post public void AddDefaultJsonPostHeader() { AddHdr(HEADER_CONTENT_TYPE, "application/json"); } // convenience for xml accept public void AddXmlAcceptHeader() { AddAcceptHdr("text/xml"); } // convenience for JSON accept public void AddJsonAcceptHeader() { AddAcceptHdr("application/json"); } } } // END PfsHttp CLASS