Simple HttpClient function to handle all Http Methods

With MVC 5 and WebApi, HttpClient provides a simple way to make API calls to another application. Here’s a sample function that can handle all Http methods.

HttpClient.SendAsync() method handles all http methods, a key part of this solution

 


private HttpResponseMessage CallHttpApi(HttpMethod method, 
	string url, 
	string jsonContent, 
	List<KeyValuePair<string,string>> headers = null)
{
	using (var client = new HttpClient())
	{
		client.DefaultRequestHeaders.Accept.Clear();
		client.DefaultRequestHeaders.Accept.
			Add(new MediaTypeWithQualityHeaderValue("application/json"));

		try
		{
			var request = new HttpRequestMessage()
			{
				RequestUri = new Uri(url),
				Method = method,
				Content = new StringContent(jsonContent, 
					Encoding.UTF8, "application/json"),
			};

			if (headers != null)
			{
				client.DefaultRequestHeaders.AsQueryable()
					.ToForEach(a => { request.Headers.Add(a.Key, a.Value); });
				headers.ForEach(a=>{request.Headers.Add(a.Key, a.Value);});
			}

			var resp = client.SendAsync(request).Result;
			resp.EnsureSuccessStatusCode();
			return resp;
		}
		catch (Exception ex)
		{
			var exRes = ex;
			if (ex is AggregateException)
			{
				exRes = ((AggregateException)ex).Flatten();
			}
			throw exRes.HandleException();
		}
	
	}
}

public static void ToForEach<T>(this IEnumerable<T> enumeration, Action<T> action)
{
	foreach (T item in enumeration)
	{
		action(item);
	}
}

public static partial class ExceptionManager
{
	public static Exception HandleException(this Exception ex)
	{
		return HandleException(ex, string.Empty);
	}

	public static Exception HandleException(this Exception ex, 
		string messageFormat, params object[] args)
	{
		return HandleException(ex, string.Format(messageFormat, args));
	}

	public static Exception HandleException(this Exception ex, string newMessage)
	{
		Exception nuEx = null;
		if (!string.IsNullOrEmpty(newMessage))
		{
			nuEx = new Exception(newMessage);
			nuEx.Data.Add(ex.Message, ex.StackTrace);
		}
		else
		{
			nuEx = ex;
			try
			{
				nuEx.Data.Add(nuEx.Message, nuEx.StackTrace);
			}
			catch { }
		}
		return nuEx;
	}
}

List<KeyValuePair<string, string>> h = new List<KeyValuePair<string, string>>();
h.Add(new KeyValuePair<string,string>("X-CUSTOM-USERID", "WHATEVER"));
h.Add(new KeyValuePair<string,string>("X-CUSTOM-INFO", "AGAIN WHATEVER"));

var resp = CallHttpApi(HttpMethod.Post, url, 
	JsonConvert.SerializeObject( products), h);
Debug.WriteLine(resp.Content);

IE 8/9 CORS support in Angular.js

Many would agree with me that to create a website to run on IE is a headache chore. I would have dropped the IE browser if we were given that choice. Our team has decided to use Angular as our primary html platform. It works great and we all loved it, until the app started to break in IE, which is caused by lack of IE cors (cross-origin-resource-sharing) support. Angular had a solution to use XDomainRequest, but removed due to its limited capabilities. Fortunately, there’s a better solution. Let’s go over the steps:

First, we have to hijack the $http service. So that it can support IE CORS when detected. On the main application where Angular is expected to access the resources (templates/API) on another server, we will modify the angular.js file to use our very own httpBackendProvider. Find the $HttpBackendProvider function and replace it as below (roughly between 9200 to 9300 line, for v1.0.7)

function $HttpBackendProvider() {
  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {
      var params = [$browser, XHR, $browser.defer, $window.angular.callbacks, $document[0], $window.location.protocol.replace(':', '')]; /*orig xhr */
      var param4ie = params.concat([msie,createHttpBackend.apply(this,params)]);
      return (angular.ieCreateHttpBackend && angular.ieCreateHttpBackend.apply(this, param4ie)) ||
        createHttpBackend.apply(this, params);
  }];
}

2nd step is to create the ieCreateHttpBackend method and that’s where we put the override logic for IE CORS support. see the code below, we are extending angular namespace with the new function ieCreateHttpBackend. Lets save it as angular.ieCors.js, be sure to wrap it as a self invoking function.

window.angular = {
  ieCreateHttpBackend: function ($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol, msie, xhr) {
    if (!msie || msie > 9) return null;

    var getHostName = function (path) {
      var a = document.createElement('a');
      a.href = path;
      return a.hostname;
    }

    var isLocalCall = function (reqUrl) {
      var reqHost = getHostName(reqUrl),
        localHost = getHostName($browser.url());

      patt = new RegExp( localHost + "$", 'i'); 
      return patt.test(reqHost);
    }

    function completeRequest(callback, status, response, headersString) {
      var url = url || $browser.url(),
        URL_MATCH = /^([^:]+):\/\/(\w+:{0,1}\w*@)?(\{?[\w\.-]*\}?)(:([0-9]+))?(\/[^\?#]*)?(\?([^#]*))?(#(.*))?$/;


      // URL_MATCH is defined in src/service/location.js
      var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];

      // fix status code for file protocol (it's always 0)
      status = (protocol == 'file') ? (response ? 200 : 404) : status;

      // normalize IE bug (http://bugs.jquery.com/ticket/1450)
      status = status == 1223 ? 204 : status;

      callback(status, response, headersString);
      $browser.$$completeOutstandingRequest(angular.noop);
    }
    var pmHandler = function (method, url, post, callback, headers, timeout, withCredentials) {
      var win =  $('[name="' + getHostName(url) + '"]')[0].id ;
      console.log('ie postMessage for url : ' + url);
      console.log( 'iframe window ' + win);
      pm({
        target: window.frames[win],
        type: 'xhrRequest',
        data: {
          headers: headers,
          method: method,
          data: post,
          url: url
        },
        success: function (respObj) {
          completeRequest(callback, 200, respObj.responseText, 'Content-Type: ' + respObj.contentType);
        },
        error: function (data) {
          completeRequest(callback, 500, 'Error', 'Content-Type: text/plain');
        }
      });
    }
    return function (method, url, post, callback, headers, timeout, withCredentials) {
      $browser.$$incOutstandingRequestCount();
      url = url || $browser.url();

      if (isLocalCall(url) ) {
        xhr(method, url, post, callback, headers, timeout, withCredentials);
      } else {
        pmHandler(method, url, post, callback, headers, timeout, withCredentials);
      }
      if (timeout > 0) {
        $browserDefer(function () {
          status = -1;
          xdr.abort();
        }, timeout);
      }
    }

  }
};

The entire IE CORS solution is base on postMessage.js , and it uses an invisible iframe to make XmlHttpRequest to another server. So we have to setup an iframe in the body

angular_ie_cors_iframe

As indicated above, we are expecting the remote server to receive the request via the ClientProxy page. We will have to setup the page later.

Next step is to make sure the js files are loaded properly. Due to the way how it is injected into Angular, be sure to load angular.ieCors.js prior to angular.js

<script src="/Scripts/jquery-1.10.2.js"></script>
<script src="/Scripts/postMessage.js"></script>
<script src="/Scripts/angular.ieCors.js"></script>
<script src="/Scripts/angular.js"></script>

Now let’s switch our focus to the ClientProxy page, which is hosted on the remote server where the resources are (html templates, api, etc). In order for CORS to work, the resource server must reply with the access-control origin headers. “*”, a wildcard origin, should be used with cautious. These headers basically tell client browser to enable CORS for the http requests.

Access-Control-Allow-Headers:Accept, Content-MD5, Content-Type, X-Requested-With
Access-Control-Allow-methods:POST, GET, OPTIONS, PUT, DELETE
Access-Control-Allow-Origin:*
Access-Control-Max-Age:1728000

Here’s the code for ClientProxy


<!DOCTYPE html>
<html>
<head>
<title></title>
<script src="/Scripts/jquery-1.10.2.js"></script>
<script src="/Scripts/postMessage.js"></script>
<script type="text/javascript">
  (function () {
    pm.bind("xhrRequest", function (data) {
      console.log(JSON.stringify(data));
      
      if (data && data.url) {
        var ret = $.ajax({
          type: data.method,
          url: data.url,
          headers: data.headers,
          data: data.data,  //forgot to include the body
          async: false
        });
        return {
          responseText: ret.responseText,
          contentType: ret.getResponseHeader("Content-Type")
        };
      }
      return '';
    });

  })();

</script>
</head>
<body style="color:#3e3e3e">
  This page is intentionally left blank
</body>
</html>


That’s pretty much it. The final point I should make is that jQuery has stopped supporting IE8/9 with v2.0; it maybe good to stick with v1.10.2

Load javascript files dynamically with jQuery getScript and promise

In my current project, I need to load set of javascript files dynamically and sequentially. To my surprise that I can’t find a decent solution on the net. End up creating my own jquery plugin to load the javascript files.

The following sample code, scriptLoader, was built with jQuery getScript and promise.

 

(function ($) {
    jQuery.fn.extend({
        scriptLoader: function (scripts) {
                var chain = $.Deferred();
                chain.resolve();
                scripts.forEach(function (script, index, array) {
                    chain = chain.then(function () {
                        return $.getScript(script, function (data, status) {
                            console.info('Loaded: ' + status + ' - '  + script);
                        });
                    });
                });
                chain.then(function () {
                    console.info('scriptLoader completed');
                });
                return chain.promise();
        }
    });
})(jQuery);

 

Here’s an example on using the scriptLoader. It’s pretty simple and straightforward


<script >
  var scripts = [
    'Scripts/ui-bootstrap-tpls-0.4.0.js',
    'Scripts/controllers/controllers.MainController.js',
    'Scripts/controllers/controllers.PrettyController.js',
    'Scripts/services/services.dataService.js',
  ];

  $(document).scriptLoader(scripts)
    .then(function () {
      angular.element(document).ready(function () {
      angular.bootstrap($('#angularContainer'), ['angularApp']);
    });
  });
 </script>

Handle Exception in C#

Why do i keep doing the same old exception handler every place i work. Here’s a boilerplate handler that I used over and over. There are two parts in the helper, first is to capture exception object message and stack trace into the Data collection. Second is to enumerate the Data object and return for print output or logging.

public static partial class ExceptionHelper
{
	public static Exception HandleException(this Exception ex)
	{
		return HandleException(ex, string.Empty);
	}

	public static Exception HandleException(this Exception ex, string messageFormat, params string[] args)
	{
		return HandleException(ex, string.Format(messageFormat, args));
	}

	public static Exception HandleException(this Exception ex, string newMessage)
	{
		Exception nuEx = null;
		if (!string.IsNullOrEmpty(newMessage))
		{
			nuEx = new Exception(newMessage);
			nuEx.Data.Add(ex.Message, ex.StackTrace);
		}
		else
		{
			nuEx = ex;
			nuEx.Data.Add(nuEx.Message, nuEx.StackTrace);
		}
		return nuEx;
	}
	
	public static WebFaultException<ErrorResponse> ProcessException (this Exception ex, string messageFormat, params string[] args)
	{
		return HandleException(ex, string.Format(messageFormat, args));
	}
        ///used in WCF, can leave out WebFaultException and use ErrorResponse directly
	public static WebFaultException<ErrorResponse> ProcessException (this Exception ex, string responseMessage )
	{
		string msg = string.Empty;
		ErrorResponse ret = null;
		List<Error> eArray = new List<Error>();
		Hashtable hData = null;
		WebFaultException<ErrorResponse> fault ;
		eArray.Add(new Error() { Message = ex.Message, StackTrace = ex.StackTrace });
		if (ex.Data.Count > 0)
		{
			try
			{
				hData = new System.Collections.Hashtable(ex.Data);
				var tlist = hData.Keys.Cast<string>().ToList();
				var d = tlist.Select(a => new Error()
					{
						Message = a,
						StackTrace = hData[a].ToString()
					});

				eArray.AddRange(d);
			}
			catch(Exception ee)
			{
				System.Diagnostics.Debug.Write(ee.Message);
			}
		}
		ret = new ErrorResponse()
			{
				Message = responseMessage,
				Errors = eArray
			};
		try
		{
                        ///eventlog is optional
			eventAppLog.WriteEntry(string.Format("error message : {0}, details : {1}", responseMessage, 
			System.Diagnostics.TraceEventType.Error );
		}
		catch { }
		
		fault = new WebFaultException<ErrorResponse>(ret, HttpStatusCode.InternalServerError);
		if (hData != null)
		{
			//add the original data details in the fault ex
			hData.Keys.Cast<string>().ToList().ForEach(a =>
			{
				fault.Data.Add(a, hData[a].ToString());
			});
		}
		return fault;
	}
}

public partial class Error
{
	public string Message{get;set;}
	public string StackTrace {get;set;}
}
public partial class ErrorResponse
{
	public string Message { get; set; }
	public List<Error> Errors { get; set; }
}

node.js + mongodb

node and Mongo

Started a node.js project several months back, lab.samlam.com. My first attempt to create a web application that utilizes all new technology:

  • node.js
  • express.js
  • mongoose.js + mongodb
  • restify.js
  • gm.js + graphicmagick
  • syntaxhighlighter
  • masonry.js
  • curl.js
  • backbone.js

It’s demo-worthy but still needs a lot of work to become fully functional. My goal is to open-source the final version when it’s done. Hopefully by late March of 2013 ( the front-end is now available on github, https://github.com/samlam/theideafarm; it will be another month for API to be ready )

I am very much intrigued by the non-blocking approach to create web application using node.js, which is built on chrome v8 engine. The result is amazing that the application is very responsive and the platform provides web developer great deal of control. Unlike many other node.js projects out there, i have elected the windows environment. My project is written on 2008 Microsoft windows server with Web Matrix IDE.

note: the lab is hosted on heroku.com