Blogger Widgets
  • Sharing Photos using SignalR
  • TFS Extenstion - allows copy work items between projects
  • Displaying jquery progressbar with ajax call on a modal dialog
  • Managing windows services of a server via a website
  • Exploring technologies available to date. TechCipher is one place that any professional would like to visit, either to get an overview or to have better understanding.

Search This Blog

Wednesday, 28 November 2012

Combining ASP.NET MVC + SignalR + KnockoutJs with WCF Dual HTTP service

Managing windows services for a server via a website seems like a good option instead of having to remote desktop or remote accessing services.

A simple ASP.NET website should suffice this requirement, Is that correct ?
No, here is a simple scenario to prove that.

User wants to start a windows service using the website, now there are many things that can go wrong :
  • Service taking longer time to process the request
  • Service was unable to start due to some failure
  • Users display shows invalid service state

To fix this issue polling every 10(sec) can be done to find the correct state of the service. But what if this clients polling be replaced with service polling only when the state of the service is changed.

Now lets dig deep into and find out how this can be done. First lets look at the architecture of "OnlineServiceManagement"


OnlineServiceManagement has got 2 parts
  • WCF Window service with Dual HTTP binding enabled
  • ASP.NET MVC website with SignalR and KnockoutJS

WCF Window service with Dual HTTP binding enabled

Note - This application uses nlog for logging
First define contracts at least one that has dual binding enabled
 [ServiceContract]
    public interface IWinServiceNotificationHandler
    {
        [OperationContract(IsOneWay = true)]
        void ServiceStatusChanged(String ServiceName);
    }

     [ServiceContract(
        Name = "WinServiceProviderService",
        SessionMode = SessionMode.Required,
        CallbackContract = typeof(IWinServiceNotificationHandler))]
    public interface IWinServiceProvider
    {
        [OperationContract]
        string Ping();

        [OperationContract]
        ServiceControllerStatus GetServiceStatus(String Identification, String ServiceName);

        [OperationContract]
        ServiceControllerStatus StartService(String Identification, String ServiceName);

        [OperationContract]
        ServiceControllerStatus StopService(String Identification, String ServiceName);

        [OperationContract]
        ServiceControllerStatus RestartService(String Identification, String ServiceName);
    }

Now implement contract behaviour
 [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single, InstanceContextMode = InstanceContextMode.PerCall)]
    public class WinServiceProvider : IWinServiceProvider
    {
        private static List _callbackList = new List();
        private static Dictionary _services = new Dictionary();
        public static readonly object _locker_ = new object();

        public string Ping()
        {
            return "I can ping";
        }

        private void RegisterClient(String Identification)
        {
            ServiceLogger.Logger.Info("Started " + System.Reflection.MethodInfo.GetCurrentMethod().Name + "Identifiction as '" + Identification + "'");
            // Subscribe the guest to the beer inventory
            IWinServiceNotificationHandler client = OperationContext.Current.GetCallbackChannel();
            if (!_callbackList.Contains(client))
            {
                _callbackList.Add(client);
            }
            ServiceLogger.Logger.Info("Completed " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
        }

        private void RegisterServiceNames(String ServiceName, ServiceControllerStatus Status)
        {
            ServiceLogger.Logger.Info("Started " + System.Reflection.MethodInfo.GetCurrentMethod().Name + "for Service '" + ServiceName + "'");

            if (!_services.ContainsKey(ServiceName))
            {
                _services.Add(ServiceName, Status);
            }
            else
            {
                _services[ServiceName] = Status;
            }

            ServiceLogger.Logger.Info("Completed " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
        }

        public static void ResetStatuses()
        {
            ServiceLogger.Logger.Info("Started " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
            try
            {
                lock (_locker_)
                {
                    string[] serviceNames = _services.Keys.ToArray();
                    foreach (string serviceName in serviceNames)
                    {
                        ServiceController sc = ServiceController.GetServices().Where(s => s.ServiceName == serviceName).FirstOrDefault();
                        _services[serviceName] = sc.Status;
                    }
                }
            }
            catch (Exception ex)
            {
                ServiceLogger.Logger.Error(ex);
            }
            ServiceLogger.Logger.Info("Completed " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
        }

        public static void NotifyClients(String ServiceName)
        {
            ServiceLogger.Logger.Info("Started " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
            ServiceLogger.Logger.Info("Found {0} callback clients", _callbackList.Count);
            try
            {
                _callbackList.ForEach(
                    delegate(IWinServiceNotificationHandler callback)
                    { callback.ServiceStatusChanged(ServiceName); });

                ResetStatuses();
            }
            catch (Exception ex)
            {
                ServiceLogger.Logger.ErrorException("Exception", ex);
            }
            ServiceLogger.Logger.Info("Completed " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
        }

        public static string HasServiceStatusChanged()
        {
            ServiceLogger.Logger.Info("Started " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
            string retStatusChanged = string.Empty;
            try
            {
                lock (_locker_)
                {
                    string[] serviceNames = _services.Keys.ToArray();
                    foreach (string serviceName in serviceNames)
                    {
                        ServiceController sc = ServiceController.GetServices().Where(s => s.ServiceName == serviceName).FirstOrDefault();
                        if (sc != null)
                        {
                            if (_services[serviceName] != sc.Status)
                            {
                                ServiceLogger.Logger.Info("Status changed for '{0}'", serviceName);
                                retStatusChanged = serviceName;
                                break;
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                ServiceLogger.Logger.Error(ex);
            }
            ServiceLogger.Logger.Info("Completed " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
            return retStatusChanged;
        }

        public ServiceControllerStatus GetServiceStatus(String Identification, String ServiceName)
        {
            ServiceLogger.Logger.Info("Started " + System.Reflection.MethodInfo.GetCurrentMethod().Name + "Identifiction as '" + Identification + "'");
            RegisterClient(Identification);
            ServiceControllerStatus retStatus = ServiceControllerStatus.StopPending;
            ServiceController sc = ServiceController.GetServices().Where(s => s.ServiceName == ServiceName).FirstOrDefault();
            if (sc != null)
            {
                retStatus = sc.Status;
            }
            RegisterServiceNames(ServiceName, sc.Status);
            //NotifyClients(ServiceName);
            ServiceLogger.Logger.Info("Completed " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
            return retStatus;
        }

        public ServiceControllerStatus StartService(String Identification, String ServiceName)
        {
            ServiceLogger.Logger.Info("Started " + System.Reflection.MethodInfo.GetCurrentMethod().Name + "Identifiction as '" + Identification + "'");
            RegisterClient(Identification);
            ServiceControllerStatus retStatus = ServiceControllerStatus.StopPending;
            ServiceController sc = ServiceController.GetServices().Where(s => s.ServiceName == ServiceName).FirstOrDefault();
            if (sc != null)
            {
                sc.Start();
                retStatus = sc.Status;
                //while (retStatus != ServiceControllerStatus.Running)
                //{
                //    System.Threading.Thread.Sleep(1000);
                //}
            }
            RegisterServiceNames(ServiceName, sc.Status);
            //NotifyClients(ServiceName);
            ServiceLogger.Logger.Info("Completed " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
            return retStatus;
        }

        public ServiceControllerStatus StopService(String Identification, String ServiceName)
        {
            ServiceLogger.Logger.Info("Started " + System.Reflection.MethodInfo.GetCurrentMethod().Name + "Identifiction as '" + Identification + "'");
            RegisterClient(Identification);
            ServiceControllerStatus retStatus = ServiceControllerStatus.StopPending;
            ServiceController sc = ServiceController.GetServices().Where(s => s.ServiceName == ServiceName).FirstOrDefault();
            if (sc != null)
            {
                sc.Stop();
                retStatus = sc.Status;
                //while (retStatus != ServiceControllerStatus.Stopped)
                //{
                //    System.Threading.Thread.Sleep(1000);
                //}
            }
            RegisterServiceNames(ServiceName, sc.Status);
            //NotifyClients(ServiceName);
            ServiceLogger.Logger.Info("Completed " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
            return retStatus;
        }

        public ServiceControllerStatus RestartService(String Identification, String ServiceName)
        {
            ServiceLogger.Logger.Info("Started " + System.Reflection.MethodInfo.GetCurrentMethod().Name + "Identifiction as '" + Identification + "'");
            RegisterClient(Identification);
            ServiceControllerStatus retStatus = ServiceControllerStatus.StopPending;
            ServiceController sc = ServiceController.GetServices().Where(s => s.ServiceName == ServiceName).FirstOrDefault();
            if (sc != null)
            {
                retStatus = StopService(Identification, ServiceName);
                retStatus = StartService(Identification, ServiceName);
            }
            RegisterServiceNames(ServiceName, sc.Status);
            //NotifyClients(ServiceName);
            ServiceLogger.Logger.Info("Completed " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
            return retStatus;
        }
    }
Now define endpoint configuration in app.config for windows service
endpoint address="" binding="wsDualHttpBinding"                  contract="WinServiceManger.Contract.IWinServiceProvider" 

That's it main components of windows service are completed. Windows service exposes some operations for website consumption and also has "IWinServiceNotificationHandler" for implementing call back to clients.

ASP.NET MVC website with SignalR and KnockoutJS

Using the default MVC template for creating the project should be sufficient. Now lets look into the details of website. Include following dependencies :
Dlls
  • SignalR
  • NLog

Scripts
  • JQuery
  • JQuery Templates Plugin
  • KnockoutJS
  • Json

Service references
  • WinServiceManger


We are using KnockoutJS that follows MVVM pattern in which Model comes first. So lets define our Model first
public class WindowsServicesModel
    {
        public List Services { get; set; }
        public WindowsServicesModel(String Identification)
        {
            LoadServices(Identification);
        }

        private void LoadServices(String Identification)
        {
            try
            {
                Services = new List()
                {
                    new WinService
                    {
                        Name = "ASP.NET State Service",
                        ServiceName = "aspnet_state",
                        Description="Provides support for out-of-process session states for ASP.NET. If this service is stopped, out-of-process requests will not be processed. If this service is disabled, any services that explicitly depend on it will fail to start.",
                        CSSClass = "one",
                        Status= ""
                    },
                    new WinService
                    {
                        Name = "Background Intelligent Transfer Service",
                        ServiceName = "BITS",
                        Description="Transfers files in the background using idle network bandwidth. If the service is disabled, then any applications that depend on BITS, such as Windows Update or MSN Explorer, will be unable to automatically download programs and other information.",
                        CSSClass = "two",
                        Status= ""
                    },
                    new WinService
                    {
                        Name = "Bluetooth Support Service",
                        ServiceName = "bthserv",
                        Description="The Bluetooth service supports discovery and association of remote Bluetooth devices.  Stopping or disabling this service may cause already installed Bluetooth devices to fail to operate properly and prevent new devices from being discovered or associated.",
                        CSSClass = "three",
                        Status= ""
                    }
                };

                foreach (WinService winService in Services)
                {
                    WinServiceManger.ServiceControllerStatus status = Global.WinServiceMangerClient.GetServiceStatus(Identification, winService.ServiceName);
                    switch (status)
                    {
                        case WinServiceManger.ServiceControllerStatus.Running:
                            winService.Status = "Running";
                            break;
                        case WinServiceManger.ServiceControllerStatus.ContinuePending:
                            winService.Status = "Continue Pending";
                            break;
                        case WinServiceManger.ServiceControllerStatus.Paused:
                            winService.Status = "Paused";
                            break;
                        case WinServiceManger.ServiceControllerStatus.PausePending:
                            winService.Status = "Pause Pending";
                            break;
                        case WinServiceManger.ServiceControllerStatus.StartPending:
                            winService.Status = "Start Pending";
                            break;
                        case WinServiceManger.ServiceControllerStatus.Stopped:
                            winService.Status = "Stopped";
                            break;
                        default:
                            winService.Status = "Unknown";
                            break;
                    }
                }
            }
            catch (Exception ex)
            {
                WebLogger.Logger.ErrorException("WindowsServicesModel.LoadServices Exception : ", ex);
            }
        }
    }
We have our model ready now, so lets define our View to be a KnockoutJS template that display list of services available.
 
Now write javascript code for updating View that is defined earlier
var koHelper = {
    ViewModel: {},
    LoadViewModel: function (resultData) {
        //var strViewModel = document.getElementById(viewModelFieldId).value;
        //var clientViewModel = ko.utils.parseJson(resultData);
        var clientViewModel = resultData;
        this.ViewModel = clientViewModel;
        ko.applyBindings(this.ViewModel);
    },
    getWindowsServices: function () {
        $.ajax({
            url: "/Home/GetWindowsServices/",
            type: 'post',
            //data: "{'customerID':'1' }",
            contentType: 'application/json',
            success: function (result) {
                koHelper.LoadViewModel(result);
                var dt = new Date();
                koHelper.UpdateStatus("Autoupdate service status by Signal-R");
            },
            error: function (jqXHR, textStatus, errorThrown) {
                var errorMessage = '';
                $('#message').html(jqXHR.responseText);
            }
        });
    },
    StartService: function (data, event) {        
        $.ajax({
            url: "/Home/StartService/",
            type: 'post',
            data: JSON.stringify( { 'ServiceName': data.ServiceName } ),
            contentType: 'application/json',
            dataType: 'json',
            success: function (result) {
                if (result != null) {
                    koHelper.LoadViewModel(result);
                    var dt = new Date();
                    koHelper.UpdateStatus("StartService");
                    //$.windowsServiceManager.performedServiceStatusChange(data.ServiceName);
                }
            },
            error: function (jqXHR, textStatus, errorThrown) {
                var errorMessage = '';
                $('#message').html(jqXHR.responseText);
            }
        });
    },
    StopService: function (data, event) {
        $.ajax({
            url: "/Home/StopService/",
            type: 'post',
            data: JSON.stringify({ 'ServiceName': data.ServiceName }),
            contentType: 'application/json',
            dataType: 'json',
            success: function (result) {
                if (result != null) {
                    koHelper.LoadViewModel(result);
                    var dt = new Date();
                    koHelper.UpdateStatus("StopService");
                    //$.windowsServiceManager.performedServiceStatusChange(data.ServiceName);
                }
            },
            error: function (jqXHR, textStatus, errorThrown) {
                var errorMessage = '';
                $('#message').html(jqXHR.responseText);
            }
        });
    },
    RestartService: function (data, event) {
        $.ajax({
            url: "/Home/RestartService/",
            type: 'post',
            data: JSON.stringify({ 'ServiceName': data.ServiceName }),
            contentType: 'application/json',
            dataType: 'json',
            success: function (result) {
                if (result != null) {
                    koHelper.LoadViewModel(result);
                    var dt = new Date();
                    koHelper.UpdateStatus("RestartService");
                    //$.windowsServiceManager.performedServiceStatusChange(data.ServiceName);
                }
            },
            error: function (jqXHR, textStatus, errorThrown) {
                var errorMessage = '';
                $('#message').html(jqXHR.responseText);
            }
        });
    },
    UpdateStatus: function (statusData) {
        var content = "
" + new Date() + "
" + statusData + "
"; content += $('#statusInfo').html() ; $('#statusInfo').html(content); } }
We have used following controller actions:-
  • /Home/GetWindowsServices/
  • /Home/StartService/
  • /Home/StopService/
  • /Home/RestartService/
Now lets look at implementing these actions
 public JsonResult GetWindowsServices()
        {
            JsonResult retValue = null;
            WebLogger.Logger.Info("Started " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
            try
            {
                if (Session["Identification"] != null)
                {
                    WindowsServicesModel wsm = new WindowsServicesModel(Session["Identification"].ToString());
                    retValue = new JsonResult()
                    {
                        Data = wsm
                    };
                }
            }
            catch (Exception ex)
            {
                WebLogger.Logger.ErrorException("Error ", ex);
            }
            WebLogger.Logger.Info("Completed " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
            return retValue;
        }

[AcceptVerbs(HttpVerbs.Post)]
        public JsonResult StartService(string ServiceName)
        {
            JsonResult retValue = null;
            WebLogger.Logger.Info("Started " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
            try
            {
                if (Session["Identification"] != null)
                {
                    WinServiceManger.ServiceControllerStatus status = Global.WinServiceMangerClient.StartService(Session["Identification"].ToString(), ServiceName);
                    //if (status == WinServiceManger.ServiceControllerStatus.Running)
                    //{
                    WindowsServicesModel wsm = new WindowsServicesModel(Session["Identification"].ToString());
                    retValue = new JsonResult()
                    {
                        Data = wsm
                    };
                    //}
                }
            }
            catch (Exception ex)
            {
                WebLogger.Logger.ErrorException("Error ", ex);
            }
            WebLogger.Logger.Info("Completed " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
            return retValue;
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public JsonResult StopService(string ServiceName)
        {
            JsonResult retValue = null;
            WebLogger.Logger.Info("Started " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
            try
            {
                WinServiceManger.ServiceControllerStatus status = Global.WinServiceMangerClient.StopService(Session["Identification"].ToString(), ServiceName);
                WindowsServicesModel wsm = new WindowsServicesModel(Session["Identification"].ToString());
                retValue = new JsonResult()
                {
                    Data = wsm
                };
            }
            catch (Exception ex)
            {
                WebLogger.Logger.ErrorException("Error ", ex);
            }
            WebLogger.Logger.Info("Completed " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
            return retValue;
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public JsonResult RestartService(string ServiceName)
        {
            JsonResult retValue = null;
            WebLogger.Logger.Info("Started " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
            try
            {
                WinServiceManger.ServiceControllerStatus status = Global.WinServiceMangerClient.RestartService(Session["Identification"].ToString(), ServiceName);
                //if (status == WinServiceManger.ServiceControllerStatus.Running)
                //{
                WindowsServicesModel wsm = new WindowsServicesModel(Session["Identification"].ToString());
                retValue = new JsonResult()
                {
                    Data = wsm
                };
                //}
            }
            catch (Exception ex)
            {
                WebLogger.Logger.ErrorException("Error ", ex);
            }
            WebLogger.Logger.Info("Completed " + System.Reflection.MethodInfo.GetCurrentMethod().Name);
            return retValue;
        }
Thats it! we are done with main components required for implementing our requirement. Complete solution is available on GitHub at OnlineServiceManagement OnlineServiceManagement

“We have to stop optimizing for programmers and start optimizing for users.” – Jeff Atwood

Tuesday, 20 November 2012

Unable to share user controls as a link between projects in ASP.NET

Sharing user control as a link between project is not advisable as per microsoft article How to: Add Existing Items to a Project. Look at note under "Adding an Existing Item as a Link" as it says

"Visual Basic Web projects, Visual C# Web projects, and other similar projects do not support links to items."

But if you still want to go with this method, then here it is how you can achieve it. Consider you have following projects in your solution
- Web application 1 => csharpbloggerapp.csproj
- Web application 2 => csharpblogtracker.csproj
- a deployment project for web app csharpbloggerapp.deploy.csproj (for csharpbloggerapp.csproj)

Now consider you have a script csharpcomm.js inside csharpblogtracker.csproj under script folder and would like to include this into csharpbloggerapp.csproj not as another file but as a link, so making changes/fixes/enhancements will be easy.

1. First go to "scripts" folder inside csharpbloggerapp.csproj, then right click on "Scripts" folder select "Add Existing Item" , browse to csharpblogtracker->scripts and select the file csharpcomm.js
2. Now from the Open button drop-down list, select Add As Link

After adding the link, compile your deploy project and you shall notice "csharpcomm.js" has not been copied.

3. Now add a "Post Build Event" for csharpbloggerapp.csproj as follows

xcopy /y $(ProjectDir)$(OutDir)..\..\csharpblogtracker\Scripts\csharpcomm.js $(ProjectDir)$(OutDir)..\Scripts
That's it... now compile your deployment project and you should find csharpcomm.js copied. Same procedure can be used for pages, user controls, resource files etc..

But correct method is to create a common assembly and add reference to this common library.

“We have to stop optimizing for programmers and start optimizing for users.” – Jeff Atwood

Wednesday, 3 October 2012

DevExpress Unable to get value of the property 'usercontrol_dxcontrol_event' : object is null or undefined

I am getting "Microsoft JScript runtime error" when running web application that uses DevExpress controls. I have got a user control hierarchy as follows:-
Default.aspx
 |
  -> Site.Master
          |
           -> LoadInvoiceTab
                  |
                   -> LoadInvoiceTabHeader
LoadInvoiceTabHeader has got some javascript code to handle client side events for DevExpress controls. script has been added toward end of the user control definition.
<%@ Control Language="C#" AutoEventWireup="true" CodeFile="LoadInvoiceTabHeader.ascx.cs" Inherits="LoadInvoiceTabHeader" %>
 
Invoice No :
Customer name :
Delivery Address :
After running the website I was getting following error message:-
Microsoft JScript runtime error: Unable to get value of the property 'LoadInvoiceTabHeader_btnSave_Click': object is null or undefined
The reason for the script error is because devexpress controls try to evaluate SaveInvoice & CancelInvoice while rendering the page, but by this time the script written for clientside events were not assigned and hence generates an error. In order to render the script in advance all you need to do is just assign id for script tab with prefix with "dxss_". So script will now become
 
That's it this should solve the issue.

One machine can do the work of fifty ordinary men. No machine can do the work of one extraordinary man. ~Elbert Hubbard, The Roycroft Dictionary and Book of Epigrams, 1923

Tuesday, 25 September 2012

Measuring performance using Fiddler API

Having used Fiddler as one of the most useful tool as a developer, would it not be easy to actually use Fiddler to measure up website performance, throughput etc. Well!! FiddlerCore API can be used to achieve this. Refer to FiddlerCode API for some samples.

Pretty cool. I have been using DevExpress ASP.NET controls for quite sometime now and I wanted to measure the performance and throughput for some of very interesting controls such as aspxcallbackpanel & aspxcallback.

All I want is a small windows app with a single form having a grid that show all of the interactions to and from the website I wanted to test. So here is how it looks when comparing performance against 30 secs max.

Steps 1. Initialize and associate all relevant events and flags for Fiddler API.
public Form1()
        {
            InitializeComponent();

            oAllSessions = new List();
            Fiddler.FiddlerApplication.OnNotification += delegate(object sender, NotificationEventArgs oNEA) { Console.WriteLine("** NotifyUser: " + oNEA.NotifyString); };
            Fiddler.FiddlerApplication.Log.OnLogString += delegate(object sender, LogEventArgs oLEA) { Console.WriteLine("** LogString: " + oLEA.LogString); };
            Fiddler.FiddlerApplication.BeforeRequest += delegate(Fiddler.Session oS)
            {
                oS.bBufferResponse = false;
                Monitor.Enter(oAllSessions);
                if (oS.fullUrl.StartsWith(sSecureEndpointHostname))
                {
                    oAllSessions.Add(oS);
                }
                Monitor.Exit(oAllSessions);
            };
            Fiddler.FiddlerApplication.AfterSessionComplete += delegate(Fiddler.Session oS)
            {
                if (bUpdateTitle)
                {
                    this.Text = ("Session list contains: " + oAllSessions.Count.ToString() + " sessions");
                }
            };
            Fiddler.CONFIG.IgnoreServerCertErrors = false;
            oFCSF = FiddlerCoreStartupFlags.Default;
        }
2. Now write code to handle start/stop monitoring of fiddler sessions
 private void btnStartStop_Click(object sender, EventArgs e)
        {
            test = new Random(120);
            if (btnStartStop.Text == "Start")
            {                
                Uri uri = new Uri(txtWebSite.Text);
                iSecureEndpointPort = uri.Port;                
                btnStartStop.Text = "Stop";
                tmrAnalyse.Enabled = true;
                tmrAnalyse.Interval = 5000;
                sSecureEndpointHostname = uri.AbsoluteUri;

                lstAnalysisData.Items.Clear();
                dgSessions.Rows.Clear();


                Fiddler.FiddlerApplication.Startup(8877, oFCSF);                
            }
            else
            {                
                Fiddler.FiddlerApplication.Shutdown();
                btnStartStop.Text = "Start";
                tmrAnalyse.Enabled = false;
            }
        }
3. code snippets for add/update session data onto grid
private void AddSession(Session oS, Dictionary whoData, int timeTaken)
        {
            DataGridViewRow row = new DataGridViewRow();
            dgSessions.Rows.Add(row);

            DataGridViewCell cell1 = new DataGridViewTextBoxCell();
            cell1.Value = oS.id;
            row.Cells["SessionID"] = cell1;

            DataGridViewCell cell2 = new DataGridViewTextBoxCell();
            cell2.Value = Ellipsize(oS.fullUrl, 60);
            row.Cells["URL"] = cell2;

            DataGridViewCell cell3 = new DataGridViewTextBoxCell();
            cell3.Value = oS.oRequest.headers.HTTPMethod;
            row.Cells["HttpMethod"] = cell3;

            DataGridViewCell cell4 = new DataGridViewTextBoxCell();
            cell4.Value = oS.responseCode;
            row.Cells["RresponseCode"] = cell4;

            DataGridViewCell cell5 = new DataGridViewTextBoxCell();
            cell5.Value = oS.oResponse.MIMEType;
            row.Cells["MIMEType"] = cell5;

            DataGridViewCell cell6 = new DataGridViewTextBoxCell();
            DataGridViewCell cell7 = new DataGridViewTextBoxCell();
            

            if (whoData.ContainsKey(NotFound))
            {
                cell6.Value = "Not found";
                cell7.Value = "Not found";                
            }
            else
            {
                cell6.Value = whoData[DataColumn1];
                cell7.Value = whoData[DataColumn2];
            }

            row.Cells["Data1"] = cell6;
            row.Cells["Data2"] = cell7;

            DataGridViewCell cell8 = new DataGridViewTextBoxCell();
            cell8.Value = timeTaken;
            row.Cells["Data3"] = cell8;

        }

        private int FindRow(Session oS)
        {
            int rowId = -1;
            for (int i = 0; i < dgSessions.Rows.Count; i++)
            {
                DataGridViewRow row = dgSessions.Rows[i];
                if (row.Cells[0].Value != null)
                {
                    if (row.Cells[0].Value.ToString() == oS.id.ToString())
                    {
                        rowId = i;
                        break;
                    }
                }
                else
                {
                    rowId = i;
                    break;
                }
            }
            return rowId;
        }

        private void UpdateSession(int rowId, Session oS, Dictionary whoData, int timeTaken)
        {
            DataGridViewRow row = dgSessions.Rows[rowId];
            row.Cells["SessionID"].Value = oS.id;
            row.Cells["URL"].Value = Ellipsize(oS.fullUrl, 60);
            row.Cells["HttpMethod"].Value = oS.oRequest.headers.HTTPMethod;
            row.Cells["RresponseCode"].Value = oS.responseCode;
            row.Cells["MIMEType"].Value = oS.oResponse.MIMEType;
            row.Cells["Data1"].Value = whoData[DataColumn1];
            row.Cells["Data2"].Value = whoData[DataColumn2];
            row.Cells["Data3"].Value = timeTaken;
        }
4. code snippet for updating grid every 5 secs
private void WriteSessionList()
        {
            try
            {
                Monitor.Enter(oAllSessions);
                foreach (Session oS in oAllSessions)
                {
                    WriteSession(oS);
                }
            }
            catch (Exception ex)
            {
                lstAnalysisData.Items.Add("Exception " + ex.Message);
            }
            finally
            {
                Monitor.Exit(oAllSessions);
            }
        }

        private void tmrAnalyse_Tick(object sender, EventArgs e)
        {           
            WriteSessionList();
        }
That's it all in place now. Some of the tiny bits were missed out in the intention highlight more important bits. Download FidderAPI.rar for more details. This is common code and can be used for any website or web applications. Mostly useful to verify throughput/speed for websites that utilises any of the following controls or JavaScript plugins :-
- asp:UpdatePanel (ASP.NET ajax control)
- $.ajax (JQuery ajax call to webservice/webpage)
- ActionResult (ASP.NET MVC action) etc.

Some people worry that artificial intelligence will make us feel inferior, but then, anybody in his right mind should have an inferiority complex every time he looks at a flower. ~Alan C. Kay

Wednesday, 19 September 2012

DevExpress Input string was not in a correct format

I have started using ASP.NET DevExpress controls quite some time now. In last couple of days I have seen a strange error on pages with the following error message :

"Input string was not in a correct format"

Here is what my page consisted of a list of controls
- ASPxTextBox
- ASPxComboBox
- ASPxButton
- ASPxCallback

I want to pass the input data of ASPxTextBox & ASPxComboBox on button click to server via ASPxCallback and store this information in a database. Not so complicated as it sounds.

I have got some Nlog tracing enabled, got try-catch for ASPxCallback and all wired up. Started testing the page and I got this error ""Input string was not in a correct format"

Started debugging. No server side exceptions and nothing wrong, do not know where the error is coming from after googling and search in DevExpress support tickets I have found how to enable callback errors.

So I have enabled tracing callback errors as mentioned by DevExpress in the article Handling Callback Exceptions on Client.

Now I have got the tracing as:-

at System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal)
at System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info)
at System.Int32.Parse(String s)
at DevExpress.Web.ASPxEditors.ListEditItemsSerializingHelper.ParseItemIndex(String serializedItem, Int32& startPos)
at DevExpress.Web.ASPxEditors.ListBoxItemsSerializingHelper.DeserializeItems(String serializedItems, Boolean sortRequired)
at DevExpress.Web.ASPxEditors.ListBoxProperties.SynchronizeItems(String serializedItems, Boolean isInsertingSyncType)
at DevExpress.Web.ASPxEditors.ASPxComboBox.SynchronizeItems(NameValueCollection postCollection)
at DevExpress.Web.ASPxEditors.ASPxComboBox.LoadPostData(NameValueCollection postCollection)
at DevExpress.Web.ASPxClasses.ASPxWebControl.LoadPostDataInternal(NameValueCollection postCollection, Boolean raisePostDataEvent)

But still do not know where the issue is. So started again looking into code step-by-step and I have found something. The items I am adding to ASPxComboBox is the issue.

aspx

 
        
javascript

var dataItems:
        [
          ["Item1","Available"],
["Item2","Available"],
["Item3","Available"],
["Item4","Available"],
["Item5","NotAvailable"],
["Item6","Available"]];
var itemid = 0;
for (var i = 0; i < dataItems.length; i++) {
 var dataItem = dataItems[i];
 if(dataItem[1] == "Available"){
   ClientCmbData.AddItem(dataItem, itemid++);
}
}


The issue occurs at ClientCmbData.AddItem(dataItem, itemid++), instead of ClientCmbData.AddItem(dataItem[0], itemid++);

So data passed in for ASPxComboBox items text value is invalid and hence parsing fails. That's it problem solved.



“The computer was born to solve problems that did not exist before.” – Bill Gates

Wednesday, 12 September 2012

State management in ASP.NET for high availability of data

ASP.NET session is the correct answer for state management. Yes that's it developers have to just use session to maintain state ie.. any data relavant to a user's session. Ways to store session state can mainly be categorized into InProc and OutProc.

InProc


Session state stored as in-memory on the web server.

Websites running in "Inproc" mode is completely dependent on the resources of the server. Limitation for number of users is dependent on the following factors
- Memory of server
- Amount of data stored per user session

As the memory used starts to exceed available memory application pool gets recycled and hence data stored is lost.

Single Web Server

Easy to configure and setup.
To enable session state as "Inproc" update web.config as follows:-


Advantages
- Easy access to data as stored in-memory

Disadvantages
- Data loss due exceeded memory utilization

Web Farm

Another method of increasing user capacity is by enabling sticky sessions on a web farm. This can achieved by using a Network Load Balancing (NLB). NLB has a feature known as "The Request Forwarder" and can be used to configure a cluster (web farm).

Sticky sessions use a HTTP cookie, which is returned for each client request that contains server instance GUID (ie.. first server that handled the request) and session ID allocated for the user. Subsequent requests will pass back server instance GUID and session ID that load balancer identifies and forwards to respective server. For mode detail explanation of this works look at technet article avalaible at http://technet.microsoft.com/en-us/library/bb734910.aspx.

Advantages
- Increased user capacity
- Easy access to data as stored in-memory

Dis-Advantages
- Partial load balance as user's are tied to specific server that served the request
- Still has possibility of data loss due exceeded memory utilization

OutProc


Session state is stored on a state server. Also this can be located on the same machine as web server or can point to another machine on your network. This mode is reliable as restarting web application does not affect state server and hence no data loss.

This mode can be configured either for a single server instance or for multiple servers on a web farm. In case of multiple web servers in a web farm,
- objects stored in session needs to be serializable
- should be installed on the same path in each of the web server in the Web farm.

1)StateServer

Session state is stored on an ASP.NET state service. Session data stored on a remote machine, no data loss due to application pool recycling. But still has the overhead of data loss if machine that has been configured as state management server is restarted.

Advantages
- No data loss due to application pool recycle

Dis-Advantages
- Is still limited based on the memory
- Reduces performance as data is read from a remote machine

2)SQLServer

session state is stored in an SQL Server database. Session data stored in a database because of which data is never lost. Machine restart will still not loose data as data is stored in a database.

Advantages
- No data loss due to application pool recycle - Data stored permanently in a database which has high reliability

Dis-Advantages
- Reduces performance as data read is from a database - Limited to memory allocated to database

3)Custom

Session state is stored on a custom provider. There are various options available for custom provider are AppFabric, Memcached etc.

AppFabric
- distributed in-memory application cache, refer to AppFabric for windows server for more details.
Memcached
- high-performance, distributed memory object caching system, refer to Memcached for more details.
SharedCache
- distributed and replicated memory object caching system, refer to SharedCache for more details.
“The most likely way for the world to be destroyed, most experts agree, is by accident. That’s where we come in; we’re computer professionals. We cause accidents.” – Nathaniel Borenstein

Monday, 16 July 2012

Various third party .NET Controls available on web

As of today there are many .NET controls developed for various technologies such as ASP.NET, Windows forms, HTML, Jquery, compression etc. Here are the list of controls available in detail.

Developed By Controls for Features Comments
DevExpress
  • WinForms
  • ASP.NET
  • ASP.NET MVC
  • WPF
  • SilverLight
  • Windows 8
  • IOS
  • Touch Enabled Apps
  • Reporting
  • Charting
  • Data Grid & Rich Text Editors
  • Ribbon, Menu, Docking
  • Pivot Grid,Scheduler, Tree List & Gauges
  • Property Grid
  • Layout Manager
  • Navigation Bar
  • Editors & Controls
  • Printing-Exporting
  • Spell Checker
  • Wizard Control
  • Application Skins
  • Themes & Skins
  • MVC Extensions
Advantages
  • Demos available for almost each and every controls
  • Support available
  • Source code available if purchased Universal or Enterprise
  • Documentation provided along with examples
Telerik
  • WinForms
  • ASP.NET
  • ASP.NET MVC
  • WPF
  • SilverLight
  • Windows 8
  • Windows Phone
  • Ready for Touch
  • Reporting
  • Data Management
  • Editors
  • Scheduling
  • Spell Checking
  • Ajax
  • Layout
  • Navigation
  • Visualization
  • Upload
  • Theming
  • Social
  • Performance
  • Interactivity
  • Charting
Advantages
  • Demos available for almost each and every controls
  • Support available
  • Documentation provided along with examples
Disadvantages
  • Source code not provided
Infragistics
  • WinForms
  • ASP.NET
  • ASP.NET MVC
  • WPF
  • SilverLight
  • Windows 8
  • Windows Phone
  • Sharepoint
  • JQuery
  • Editors
  • Frameworks
  • Office Support
  • Grids
  • Interactions
  • Layouts
  • Lists
  • Menus
  • Schedules
  • Charts
Advantages
  • Demos available for almost each and every controls
  • Support available
  • Documentation provided along with examples
  • Source code available if purchased NetAdvantage Ultimate
Xceed
  • WinForms
  • ASP.NET
  • WPF
  • Silverlight
  • Compression
  • Networking
  • Encryption
  • Chart
  • Grid
  • Compression
  • Zipping
  • Encryption
  • FileTransfer
Advantages
  • Demos available for almost each and every controls
  • Support available
  • Documentation provided along with examples
  • Source code available if purchased BluePrint subscription
VIBlend
  • WinForms
  • WPF
  • Silverlight
  • Data grid
  • Navigation bars
  • Ribbon Interface
  • Treeview, calendar, combo box etc
  • Menu
Advantages
  • Demos available for almost each and every controls
  • Support available
  • Documentation provided along with examples
  • Source code available if purchased with VIBlend Premium
9Rays.NET
  • WinForms
  • WPF
  • Silverlight
  • Encryption
  • Obfuscator
  • Decompiler
  • Grid
  • Tree view
  • Obfuscator
  • Decompiler
Advantages
  • Demos available for almost each and every controls
  • Support available
  • Documentation provided along with examples
  • Source code available if purchased with Enterprise License
Copyright © 2013 Template Doctor . Designed by Malith Madushanka - Cool Blogger Tutorials | Code by CBT | Images by by HQ Wallpapers