Wednesday, November 23, 2016

HTTP Call - Differentiate Request and Response with some id

On most cases, user expect last requested service call results to be displayed in UI when multiple service call are made (For Ex: Search textbox to search something will make multiple calls).

We can achieve this with HTTP headers, Let us see the implementation,

First on MVC side we can check custom header present in request or not and then return that header back to response

public class SomeCustomFilter : ActionFilterAttribute
    {
        public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
        {
            if (actionExecutedContext.Request.Headers.Contains("Custom-Request-Id"))
            {
                string HttpRequestID = actionExecutedContext.Request.Headers.GetValues("Custom-Request-Id ").FirstOrDefault();
                actionExecutedContext.Response.Headers.Add("Custom-Request-Id ", HttpRequestID);
            }

        }

    }

Register this filter in global.asax


GlobalConfiguration.Configuration.Filters.Add(new SomeCustomFilter());


Now we are ready at service side, to get request header and return the same value as response header

Next send some header and receive at client side, lets take AngularJS $http for sample

var customRequestId = 0;

    function SomeMethod(url, data) {
        //Increase that request id on each service call, to make it unique
        customRequestId += ;
        var customHeaders = {‘
            Custom - Request - Id’: customRequestId
    };

    $http({
        method: 'POST',
        url: url,
        headers: customHeaders,
        data: data
    })
        .then(
            function(data) {
                //check if response and request are matches with latest service call
                var currentRequestId = parseInt(data.headers("Custom-Request-Id"));
                if (customRequestId === currentRequestId) {
                    //your logic goes here…

                }
            },
            function(errorData, status, headers, config) {});
}

Thats it, now your service call is get latest values to display in UI.

Wednesday, November 9, 2016

AngularJS - JavaScript - Client Side error logging

Usually for ServerSide logging we can use many error logging tools (For ex: elmah, log4net etc.,) to log errors into database and email. But for client side JavaScript framework we should include some extra code or some tools available (for ex: JSNLog etc.,). Here am going to explain how custom we do that,

First create JavaScript file "errorlog.js" and copy paste below code,

var errorLoggingServerURL = "Error/Log";

function logErrorToServer(ex, stack) {
    if (ex == null) return;

    if (stack == null && ex.stack != null) stack = ex.stack;

    // format output
    var out = ex.message != null ? ex.name + ": " + ex.message : "JavaScript Exception";
    if (stack != null) out += "\n  at " + stack.toString();

   
    // send error message
    $.ajax({
        type: 'POST',
        url: errorLoggingServerURL,
        data: { message: escape(out) }
    });

}

Function.prototype.trace = function () {
    var trace = [];
    var current = this;
    while (current) {
        trace.push(current.signature());
        current = current.caller;
    }
    return trace;
}

Function.prototype.signature = function () {
    var signature = {
        name: this.getName(),
        params: [],
        toString: function () {
            var params = this.params.length > 0 ?
                "'" + this.params.join("', '") + "'" : "";
            return this.name + "(" + params + ")"
        }
    };
    if (this.arguments) {
        for (var x = 0; x < this.arguments.length; x++)
            signature.params.push(this.arguments[x]);
    }
    return signature;
}

Function.prototype.getName = function () {
    if (this.name)
        return this.name;
    var definition = this.toString().split("\n")[0];
    var exp = /^function ([^\s(]+).+/;
    if (exp.test(definition))
        return definition.split("\n")[0].replace(exp, "$1") || "anonymous";
    return "anonymous";
}

window.onerror = function (msg, url, line) {
    if (arguments != null && arguments.callee != null && arguments.callee.trace)
        logErrorToServer(msg, arguments.callee.trace());

}


In AngularJS, we can have custom logging as follows,

To override AngularJS default logging and to write custom logging use as below,

 app.factory('$exceptionHandler', function () {
        return function (exception, cause) {
            //Javascript Error log will catch this
            logErrorToServer(exception);
        };
    })

Or to use both angularJS default logging and custom logging use as below

//Exception log decorator
 $provide.decorator('$exceptionHandler', ['$delegate', function ($delegate) {
    return function (exception, cause) {
     $delegate(exception, cause);
     logErrorToServer(exception);
    };
 }]);



In Server Side, we can receive the Ajax call and use any logging tool to log error, For ex, here am using Elmah to log error, it uses MVC action controller and using logging as custom class named JavaScriptException

public class ErrorController : Controller
    {
public void Log(string message)
        {
            ErrorSignal
                .FromCurrentContext()
                .Raise(new JavaScriptException(HttpUtility.UrlDecode(message)));
     }

   }

Thursday, October 27, 2016

C# - Passing Linq condition as parameter

We can pass LINQ conditions dynamically as parameter, Lets consider simple example to get Single property and multiple properties by condition. We can use this for Generic Repository Pattern also.

Implementation below,

      public Student GetSingleObjectByCondition(System.Func<Student, bool> predicate)
        {
                var result = default(Student);
            using (var efContext = new DbContext())
            {
                result = efContext.Students.FirstOrDefault(predicate);
            }
            return result;
 }    

     public List<Student> GetMultipleObjectsByCondition(Func<Student, bool> predicate)
        {
            var result = default(List<Student>);
            using (var efContext = new DbContext())
            {
                result = efContext.Students.Where(predicate).ToList<Student>();
            }
            return result;
  }          

    }



How to call the method,

   Func<Student, bool> selector = str => str.Name == "Balaji";

  var student = _studentRepository.GetSingleObjectByCondition(selector);



 Func<Studentbool> selector = str => str.Rank <= 5;


  var students = _studentRepository.GetMultipleObjectsByCondition(selector);


Saturday, August 13, 2016

AngularJS - Bootstrap Datepicker Model Formatter

I have case to show datepicker for textbox, we can simply bind DateString field to textbox and update. But if we use BootStrap uibDatePicker then it requires to format as Date object before binding to ngModel.

So to resolve this issue, i have created directive to format ngModel value before binding and also parse back to string before updating to controller.

To check how to create BootStrap datepicker check here http://angular-ui.github.io/bootstrap/versioned-docs/1.3.3/#/datepickerPopup 

Just create Directive as follows

    app.directive('datePickerModelFormatter', function () {
        return {
            restrict: 'A',
            require: 'ngModel',
            link: function (scope, element, attr, ngModel) {
                function dateToString(dateValue) {
                    if (dateValue != null) {
                        var dateTimeToReturn = new Date(dateValue);
                        return dateTimeToReturn.toISOString();
                    }
                    return dateValue;
                }

                function stringToDate(stringValue) {
                    if (stringValue != null) {
                        var newOffsetDateTime = new Date(stringValue);
                        return new Date(newOffsetDateTime.setMinutes(newOffsetDateTime.getMinutes() + newOffsetDateTime.getTimezoneOffset()));
                    }
                    return stringValue;
                }

                ngModel.$parsers.push(dateToString);
                ngModel.$formatters.push(stringToDate);
            }
        };

    });



and on HTML just include this model

  <p class="input-group">
          <input type="text" class="form-control" uib-datepicker-popup="{{format}}" ng-model="dt" is-open="popup1.opened" datepicker-options="dateOptions" ng-required="true" close-text="Close" alt-input-formats="altInputFormats" date-picker-model-formatter />
          <span class="input-group-btn">
            <button type="button" class="btn btn-default" ng-click="open1()"><i class="glyphicon glyphicon-calendar"></i></button>
          </span>
        </p>


Thats it, it will convert to DateObject and Return back as StringObject (ISOString format)

Tuesday, June 28, 2016

AngularJS - BootStrap Popover Directive

In some cases we need to show some popover as tooltip or as dialog

Here am going to use BootStrap Popover, this plugin is part of BootStrap.js file or we can include spearately. For more information about that read here 

I am going to create simple popover

Step 1; Create your html pages, include BootStrap js files, AngularJS, JQuery basic setups

Step 2: Here is what I created directive to make PopOver work with AngularJS, add this directive to your application

var app = angular.module('appModuleName');

app.directive('popover', ['$compile',function ($compile) {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            $(element).popover({
                html: true,
                title:  attrs.popoverTitle || "Header",
                content: function () {
                    return $compile($("#" + attrs.popoverContent).html())(scope);
                },
                placement: attrs.popoverPlacement || "top"
            });
        }
    };

}]);


Step 3: In your HTML, just use this directive and pass attributes

<input type="button" popover popover-title="Header Text" popover-content="popover-content-id" popover-placement="top"/>

Step 4: Here you can pass your Title, ContentId, placement (Top, Bottom, Right, Left) etc.  This popover-content-id is div with contents

  <div id="popover-content-id" class="hide">
Some content here..
  </div>