Wednesday, May 30, 2012

Different ways for calling a code behind function from Javascript

Recently, one of my colleague asked about the different ways for calling a code behind function from JavaScript. There are different ways to call a code behind function and I decided to list down here each with example.

According to me, there are four main possible ways to call a function from Javascript:

1. Pagemethods in JS AND WebMethod in code behind class
2. IPostBackEventHandler in
codebehind class AND _doPostBack in JS 
3. ICallbackEventHandler in code behind class
4. Ajax/Jquery AND ASHX handler

Lets check each of above methods
with example and explanation.

1. Pagemethods in JavaScript AND WebMethod in cs

For using Pagemethods in JavaScript, we need to add Script Manager on aspx page. For using Ajax .Net (script manager, update panel) we need to add below settings in web.config and also System.Web.Extensions assembly is required.

<configuration>
    <system.web>
        <pages>
            <controls>
                <add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            </controls>
        </pages>   
    </system.web>
</configuration>
  

ASPX Page Code:

<script language="javascript" type="text/javascript">
    function GetCityValue() {
        PageMethods.GetCity("USA", onSucceeded, onFailed);
    }
    function onSucceeded(result, userContext, methodName) {
        document.getElementById("div1").innerHTML = result;
    }
    function onFailed(error, userContext, methodName) {
        alert("An error occurred")
    }
</script>

<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="true">
</asp:ScriptManager>
   
    <div>
<input type='button' name="btncity"  value="GetCityValue" onclick="javascript:GetCityValue()"/></div>
    <div id="div1"></div>
 


Codebehind Code:

[System.Web.Services.WebMethod()]
        public static string GetCity(String strCountry)
        {
            string strCity = string.Empty;
            if (strCountry == "USA")
                strCity = "NewYork";
            else
                strCity = "OtherCity";
            return strCity;
        }


Here 2 things need to take care:

1. Method in cs file must be public static and with attributes [System.Web.Services.WebMethod()]
2. Set EnablePageMethods="true" in Scriptmanager

2. IPostBackEventHandler in code behind class AND __doPostBack in JS

ASPX Page Code:

<script language="javascript" type="text/javascript">
    function GetCityValue() {
        var pageId = '<%=  Page.ClientID %>';
        __doPostBack(pageId, "USA");
    }
</script>
   
    <div>
<input type='button' name="btncity"  value="GetCityValue" onclick="javascript:GetCityValue()"/></div>
    <div id="div1"></div>
<asp:Label id="lblInfo" runat="server"></asp:Label>

Codebehind Code:

public partial class SampelForm : System.Web.UI.Page, IPostBackEventHandler
    {

        public string GetCity(String strCountry)
        {
            string strCity = string.Empty;
            if (strCountry == "USA")
                strCity = "NewYork";
            else
                strCity = "OtherCity";
            return strCity;
        }

        public void RaisePostBackEvent(string eventArgument)
        {
            string val = GetCity(eventArgument);
            lblInfo.Text += "City - " + val;
        }
    }


Here, with IPostBackEventHandler, Page is submitted to server (postback) and so user experience will NOT be as good compare to other methods.


3. ICallbackEventHandler in code behind class


ASPX Page Code:

<script language="javascript" type="text/javascript">
    function GetCityValue() {
        CallToServer('USA');
    }

    function ReceiveServerData(arg, context) {
        document.getElementById("div1").innerHTML = "Date from server: " + arg;
    }
</script>
   
    <div>
<input type='button' name="btncity"  value="GetCityValue" onclick="javascript:GetCityValue()"/></div>
    <div id="div1"></div>
<asp:Label id="lblInfo" runat="server"></asp:Label>

Codebehind Code:

public partial class SampelForm : System.Web.UI.Page, IPostBackEventHandler
{

        public string GetCity(String strCountry)
        {
            string strCity = string.Empty;
            if (strCountry == "USA")
                strCity = "NewYork";
            else
                strCity = "OtherCity";
            return strCity;
        }

        public void RaisePostBackEvent(string eventArgument)
        {
            string val = GetCity(eventArgument);
            lblInfo.Text += "City - " + val;
        }
}

Here, with ICallbackEventHandler, Page is NOT submitted to server and so user will experience a quick response from server (No Postback). 

4. Ajax/Jquery AND ASHX handler

ASPX Page Code:

//JQuery JS File is required.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js" type="text/javascript"></script>

<script language="javascript" type="text/javascript">

    function GetCityValue() {
        $.ajax({
            type: "POST",
            url: "AjaxHandler.ashx?method=getcity",
            dataType: "text",
            success: ReturnData2,
            error: function(XMLHttpRequest, textStatus, errorThrown) {
                alert(textStatus);
            }
        });
    }

    function ReturnData2(data) {
        $("#div1").text(data);
    }

</script>
    <div>
<input type='button' name="btncity"  value="GetCityValue" onclick="javascript:GetCityValue()"/></div>
    <div id="div1"></div>


Codebehind Code:

First of all we need to create a Handler class file. To add http handler class file (.ashx), right click on Project Name in Solution explorer and click on Add New Item. Click on Generic Handler and click Add button. It will add .ashx file, here in our example we name it as AjaxHandler.ashx.


Now copy the below code in ProcessRequest method:


        public void ProcessRequest(HttpContext context)
        {
            if (context.Request.QueryString["method"] == null)
                return;
            string methodname = context.Request.QueryString["method"];
            MsgResponse objResponse = new MsgResponse();
            string Returnmsg = string.Empty;
            switch (methodname)
            {
                case "getcity":
                    context.Response.ContentType = "text/plain";
                    Returnmsg = Getcity();
                    break;
            }
            context.Response.Write(Returnmsg);
        }

        private string Getcity()
        {
            return "NewJersey";
        }



Here, we pass the method name in querystring from Javascript Ajax call (url: "AjaxHandler.ashx?method=getcity",) and check that method name in ASHX handler. Finally, what we write to context.Response.Write will be send back to Javascript. Here, we can also use JSON to send objects in JSON format. 


Here, each way has its own advantage and disadvantage. In my opinion method 1 with Pagemethods is useful if you want to call codebehind method rarely. If you are calling server side functions more frequently, its better to use 4th method (Ajax and ASHX handler) to call server side function.


Happy Programming !!!

Sunday, January 29, 2012

Get Latest from TFS and Build project through batch file

Recently, We had requirement where Testing team required daily build of project for Testing. So I decided to automate the process with help of batch file.

Approach for making build process automated is to use Team Foundation Build Service. Team Foundation Build Service is a Windows service that is listed in different locations within the operating system. Where it is listed depends on whether Team Foundation Build Service is running as a Windows service or an interactive service.

For using Team Foundation build service, you need to learn about the build service, agents, and controllers. 

- One needs to configure and manage Team Foundation Build Service to enable your team to automatically and consistently build, test, and deploy your software in a distributed environment.
 

- Then need to install the build service and enable it to build projects that are under version control in team project. 

- Then create and manage build controllers, which handle requests for queued builds, and build agents, which handle the work of building, testing, and deploying your application. 


So overall approach is useful if you are developing Product with large code base and have large teams for developing different modules. Complete understanding of Team Foundation Build System on MSDN is available at

http://msdn.microsoft.com/library/dd793166%28VS.100%29.aspx

But we require something simple for our small project which creates Build for Testing Team as well as for release and I decided to make a batch file which
- Takes Latest from TFS
- Prepare build of project with MSBuild command
- Logs the error while building project
- Sends the email for success / failure.
- Then configured to run created batch file daily through Windows Task Scheduler.

Batch file works in below way:

- sets the enviornment variables so that Commands which can be run on VS Command prompt can also run from batch file with below command:


call "C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat" (Set path based on installed VS Version)

- Get latest from TFS (Directory must be mapped with TFS)


- Get Latest operation is done through tf get command



tf get "%Solutiondir%" /force /recursive /login:Installshield,SHSH@kk5

- prepare build through msbuild command



msbuild "%Solutiondir%\WinTestApp.sln" /t:rebuild /p:Configuration=Release;Platform="x86";DefineConstants="SSWind SSAdmin SSNKDTT SSCompany10";OutDir=bin\BuildOutput\ /fileLogger /flp:logfile="%ErrLogFilePath%";errorsonly

- msbuild command sets Configuration, Platform and conditional compilation symbols
and logs the Error occurred during build process in text file

- copies all dlls / exe to specified destination directory (folder name created with DateTime format)


- Email is send to specified sender with successful or failure message


- Email send with Error Log as attachment


- Email send through Blat utility(Blat is a Win32 command line utility that sends eMail using SMTP)


Points to take care:


- Change the path of Project Directory and destination folder and also set the Email Variables (From, to, user, pwd)

- Spaces should be avoided in name of folders as spaces may create problem in batch files


- Blat official website for downloading exe and for sample examples: http://www.blat.net/


- For using Blat to send mail, download the files and copy blat.exe (and other supporting files) to some folder (say blat) and run command as below to send mail:



cd E:/tarak/blat :: move to installation folder


blat %tempmail% -to %tomail% -f %frommail% -server %serveradd% -subject "Build Exe Failed" -u %mailuser% -pw %mailpwd% -attacht D:\Projects\BuildErr\errors.txt

Batch file can be downloaded from below URL:
https://docs.google.com/open?id=0B0L2UE58PUp8YWUyNDU5NDItOTcyMC00NGVhLWEzODItMzcwZTA5YjRhYWMx

You can always send comments for any suggestions or any assistance for further enhancement.

Happy Programming !!!

Monday, October 10, 2011

Compact Access 2007 Database using JRO / DAO

In one of my winform project, we are using Sql Server as well as Microsoft Access 97 as Database. And since size of MS Access DB file grows, at some point of time we Compact the Access Database file through coding by .Net. Today, I am sharing my experience on using different techniques to compact Access DB file using .Net.

We are using Microsoft Jet and Replication Objects 2.6 Library (JRO) to compact Access 2007 Database. But during last week we found two problems in using JRO:

1. JRO was NOT working on 64 bit Computer. I tested on Windows Server 2008 R2 and it fail to Load. (JRO might work on 64 bit if you have MS Office installed)
2. When JRO compacts DB (on XP 32bit), database file created by compaction is of Access 2002 - 2003 File format. So if your Original file is of 2007 Format then after compaction by JRO, DB File is converted to 2002 - 2003 File format.

For solving above 2 problems, I have then used DAO to compact database, which is more accurate and also worked on 64bit Server.

Here, I am giving steps to implement Compaction using JRO and DAO both.

Steps to compact Access DB using JRO:

App.config file:
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="SourceDB" value="Provider=Microsoft.ACE.OLEDB.12.0;Data Source=D:\Test\Test2007.accdb;Jet OLEDB:Engine Type=5"/>
<add key="DestDB" value="Provider=Microsoft.ACE.OLEDB.12.0;Data Source=D:\Test\Test2007BK.accdb;Jet OLEDB:Engine Type=5"/>
</appSettings>
</configuration>


1. Create a winform application and add a reference of Jet and Replication Objects 2.6 Library. See the diagram below:

2. Add form to solution and add below code in form Load event:

string SrcDBName = ConfigurationManager.AppSettings["SourceDB"];
string DestDBName = ConfigurationManager.AppSettings["DestDB"];

        int ReturnCode = 0;
        JRO.JetEngine objJRO = null;
        try
        {
            objJRO = new JRO.JetEngine();
            objJRO.CompactDatabase(SrcDBName, DestDBName);
        }
        catch (Exception ex)
        {
            StackTrace STrace = new StackTrace(ex, true);
            StackFrame StkFrame = STrace.GetFrame(STrace.FrameCount - 1);
            string Disp_Msg = "Message:\t" + ex.Message + Environment.NewLine;
            Disp_Msg += "Error Date:\t" + DateTime.Now.ToString("dddd, MMM d yyyy HH:mm:ss");

            File.AppendAllText(Path.GetDirectoryName(Application.ExecutablePath) + @"\CompactErr.txt", Disp_Msg + Environment.NewLine + "Stack Trace:\t" + ex.StackTrace + Environment.NewLine + Environment.NewLine);
        }
        finally
        {
            Marshal.ReleaseComObject(objJRO);
            objJRO = null;
        }

3. Most Important: change the Target Platform to x86 (From Project property window -> Click on Build tab and then change Platform Target to x86.

4. Run the application and will create new compacted Access DB file. But as I mention earlier its format will always be 2002-2003 format.













Steps using DAO:

1. Create a winform application and Add a reference of DAO - Microsoft Office 12.0 Access Database Engine Object Library, and the DLL is ACEDAO.DLL. See the diagram below:

2. Add form to solution and add below code in form Load event:

using AccInterop = Microsoft.Office.Interop.Access;
AccInterop.Dao.DBEngine objDBEngine = null;

string SrcDBName = ConfigurationManager.AppSettings["SourceDB"];
string DestDBName = ConfigurationManager.AppSettings["DestDB"];
objDBEngine = new AccInterop.Dao.DBEngine();
objDBEngine.CompactDatabase(SrcDBName, DestDBName);

3. You can keep target platform to "Any CPU" or x86. If you keep Any CPU then you need to install MS Access Database Engine 2010 - x64 version. And if you keep x86 then you need to install MS Access Database Engine 2010 - x86 version.

4. Run the application and will create new compacted Access DB file. Format of compacted file will be same as Original file format.


5. we need to install 2 components for DAO to work correctly.
5.1. Microsoft Access Database Engine 2010 (x86 or x64).
Link from MSDN to download: http://www.microsoft.com/download/en/details.aspx?id=13255
5.2. Microsoft Office 2010: Primary Interop Assemblies.
Link from MSDN to download: http://www.microsoft.com/download/en/details.aspx?id=3508

If you have any queries, you can write comments and I will be glad to reply you.

Happy Programming !!!

Thursday, June 2, 2011

Background Worker Example - Filling dataset in separate thread - Part 2

In my previous article [BackgroundWorker Component Overview in Winforms - Part 1], I described the working of BackgroundWorker component in Winform Application. In this article, I will demonstrate how to use the BackgroundWorker component to run a time-consuming operation on a separate thread. Example fills the dataset in background thread and also shows progress-bar while method is running.

First I created a class which inherits from BackgroundWorker Class which contains following key elements:

  1. An Enum ActionType : which contains Enum of Actions to do in background. i.e. FillCustData, DownloadCustImgs, etc will be used in method OnDoWork
  2. A public variable DoWorkArgs of type Dictionary<String, Object> for passing Arguments in key, value pair to worker method.
  3. A public class ResultData which contains properties like ResultObject, MsgText, PassedArgs etc to pass information from worker thread to UI layer. So UI layer can know what happened during background and take action based on Result.
  4. A protected override void OnDoWork (DoWorkEventArgs e) method - a key method which is executed during in separate thread.
  5. A winform with Button to start process in background and progressbar component to show progress while method is executing in background.

Here is the code for custom APKWorker Class which inherits from BackgroundWorker Class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.ComponentModel;

namespace TemplateApp
{
    public class APKWorker : BackgroundWorker
    {
        private ActionType ActionName { get; set; }
        private DataTable dtResult = null;
        public Dictionary<String, Object> DoWorkArgs = new Dictionary<string, object>();
       
        public APKWorker()
        {
            this.WorkerReportsProgress = true;
            this.WorkerSupportsCancellation = false;
        }

        public APKWorker(ActionType ActionName) : this()
        {
            this.ActionName = ActionName;
        }

        protected override void OnDoWork(DoWorkEventArgs e)
        {
            switch (this.ActionName)
            {
                case ActionType.RegisterUser:
                    //Call to method RegisterUser()
                    break;
                case ActionType.Insert_Usage_Statistic:
                    //Call to method Insert_Usage_Statistic()
                    break;
                case ActionType.FillUsers:

                    int deptid = 0;
                    if (DoWorkArgs.Keys.Contains("deptid"))
                        deptid = (int)DoWorkArgs["deptid"];


                    dtResult = new DataTable();
                    dtResult.Columns.Add("UID", Type.GetType("System.Int32"));
                    dtResult.Columns.Add("UserName", Type.GetType("System.String"));
                    DataRow dr = null;
                    this.ReportProgress(30, "Started");
                    System.Threading.Thread.Sleep(2000);
                    for (int i = 0; i < 5; i++)
                    {
                        dr = dtResult.NewRow();
                        dr["UID"] = i;
                        dr["UserName"] = "Test" + i.ToString();
                        dtResult.Rows.Add(dr);
                    }
                    this.ReportProgress(80, "Data Filled");
                    System.Threading.Thread.Sleep(2000);
                    e.Result = new ResultData { PassedArgs = DoWorkArgs, MsgText = "Data Filled.", MsgType = ResultData.MessageType.Success, ResultObject = dtResult };
                    this.ReportProgress(100, "Completed");
                    break;
            }
            base.OnDoWork(e);
        }

        public enum ActionType
        {
            RegisterUser,
            Insert_Usage_Statistic,
            FillUsers
        }
    }

    public class ResultData
    {
        public Object ResultObject { get; set; }
        public string MsgText { get; set; }
        public MessageType MsgType { get; set; }
        public Dictionary<String, Object> PassedArgs { get; set; }

        public enum MessageType
        {
            Success,
            Failure
        }       
    }

}

Code to write in Winform for Calling background worker class:

        private void btnTest_Click(object sender, EventArgs e)
        {
            this.progressBar1.Minimum = 0;
            this.progressBar1.Maximum = 100;
            APKWorker objWorker = new APKWorker(APKWorker.ActionType.FillUsers);
            objWorker.DoWorkArgs.Add("userid", 10);
            objWorker.DoWorkArgs.Add("deptid", 3);
            objWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(objWorker_RunWorkerCompleted);
            objWorker.ProgressChanged += new ProgressChangedEventHandler(objWorker_ProgressChanged);
            objWorker.RunWorkerAsync();

        //Implementation Example 2:
        //APKWorker objWorker = new APKWorker();
        //objWorker.DoWork += new DoWorkEventHandler(objWorker_DoWork);
        //objWorker.RunWorkerAsync();
        //void objWorker_DoWork(object sender, DoWorkEventArgs e)
        //{
        //    MessageBox.Show("hello");
        //}
        //Above example is useful, if you need to implement some custom logic in DoWork method. Here, first don't pass Actionname from Constructor,
        //then add the 2nd line - objWorker.DoWork += new DoWorkEventHandler(objWorker_DoWork); and write custom logic in objWorker_DoWork
        }       

        void objWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            this.progressBar1.Value = e.ProgressPercentage;
            this.lblMsg.Text = (string)e.UserState;
        }

        void objWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            ResultData ResultObj = (ResultData)e.Result;
            DataTable dtUser = (DataTable)ResultObj.ResultObject;
            MessageBox.Show(ResultObj.PassedArgs["deptid"].ToString());
            MessageBox.Show(dtUser.Rows[2]["UserName"].ToString());
            MessageBox.Show("Done");
        }


Hope this example will help to all who wants to use Background worker class to run long running methods in separate thread. Feel free to post your comments.

Background Worker Overview with Example in Winforms - Part 1

Recently, while working on Winform Application, we require certain time consuming tasks on Form load to run in separate Thread. We decided to use Background Worker Component in our application. However, there is need that Background Component will be used in multiple forms. So I decided to create a class which inherits from BackgroundWorker Class and implemented certain common functionality over there. I like to share the code and overview of Background worker class.

BackgroundWorker Component Overview:

The BackgroundWorker class allows you to run an operation on a separate, dedicated thread. Time-consuming operations like
  •     Image downloads
  •     Web service invocations
  •     File downloads and uploads (including for peer-to-peer applications)
  •     Complex local computations
  •     Database transactions
  •     Local disk access
can cause your user interface to hang while they are running. When you want a responsive UI and you are faced with long delays associated with such operations, the BackgroundWorker component provides a convenient solution.

The BackgroundWorker component gives you the ability to execute time-consuming operations asynchronously ("in the background"), on a thread different from your application's main UI thread.

To use a BackgroundWorker, you simply tell it what time-consuming worker method to execute in the background, and then you call the RunWorkerAsync method. Your calling thread continues to run normally while the worker method runs asynchronously. When the method is finished, the BackgroundWorker alerts the calling thread by firing the RunWorkerCompleted event, which optionally contains the results of the operation.

The BackgroundWorker component is available from the Toolbox, in the Components tab. To add a BackgroundWorker to your form, drag the BackgroundWorker component onto your form. It appears in the component tray, and its properties appear in the Properties window.

By using a pattern of method calls (RunWorkerAsync, ReportProgress) and event callbacks (DoWork, ProgressChanged, RunWorkerCompleted), BackgroundWorker helps you easily create a background thread and factor out the stuff that should be running on the background thread versus the foreground thread. 

If your background operation requires a parameter, call RunWorkerAsync with your parameter. Inside the DoWork event handler, you can extract the parameter from the DoWorkEventArgs.Argument property. 

Below image shows the flow of working of Background Worker model.


Above is the brief overview of how Background worker class works and what are its key events and methods. In the next article [Background worker example - Filling dataset in separate thread - Part 2], I explained working of Background worker class with code, which fills the Dataset in background and also shows the progress-bar while running the process in background.