Sunday, January 29, 2012

Creating a Simple Auto-Complete TextBox with ASP.Net Ajax

AutoComplete is an ASP.NET AJAX extender that can be attached to any TextBox control, and will associate that control with a popup panel to display words that begin with the prefix typed into the textbox. The dropdown with your words supplied by a web service is positioned on the bottom left of the text box.
When you have typed more content than the specified minimum word length, a popup will show words or phrases starting with that value. We'll create an auto-complete textbox by following these steps.

1.    Create an .aspx page and add the following CSS to <head> tag.

<style type="text/css">
        /*AutoComplete flyout */
        .autocomplete_completionListElement
        {
            margin: 0px !important;
            background-color: inherit;
            color: windowtext;
            border: buttonshadow;
            border-width: 1px;
            border-style: solid;
            cursor: 'default';
            overflow: auto;
            height: 200px;
            text-align: left;
            left: 0px;
            list-style-type: none;
        }
        /* AutoComplete highlighted item */
        .autocomplete_highlightedListItem
        {
            background-color: #ffff99;
            color: black;
            padding: 1px;
        }
        /* AutoComplete item */
        .autocomplete_listItem
        {
            background-color: window;
            color: windowtext;
            padding: 1px;
        }
</style>

2.    Add a ToolkitScriptManager to <form> tag.

<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="true">
</asp:ScriptManager>

3.    Add an textbox and button servercontrol to <form> tag. Here, we use javascript “onkeydown” event to caugh the “Enter” press.

<asp:TextBox ID="txtQuery" runat="server" Width="300px" Height="20px" autocomplete="off" onkeydown="if(window.event.keyCode == 13){document.getElementById('btnSearch').click();};"></asp:TextBox><asp:Button ID="btnSearch" OnClick="btnSearch_Click" runat="server" Text="Search" CausesValidation="False">
</asp:Button>

4.    Add the following button click event in code-behind.

protected void btnSearch_Click(object sender, EventArgs e)
        {
            if (txtQuery.Text != "")
            {
          //when you press “Search” button, it go to search.aspx.
                Response.Redirect("~/search.aspx?query=" + txtQuery.Text);
                //you need to get “query” QueryStirng for further processing in search.aspx page.
            }
            else
            {
                Response.Redirect("search.aspx");
            }
        }

5.    Add an AutoCompleteExtender as below.

<asp:AutoCompleteExtender ID="autoComplete1" runat="server" DelimiterCharacters=";,:"      CompletionListHighlightedItemCssClass="autocomplete_highlightedListItem" CompletionListItemCssClass="autocomplete_listItem"        CompletionListCssClass="autocomplete_completionListElement" CompletionSetCount="20" EnableCaching="true" CompletionInterval="500" MinimumPrefixLength="1" ServiceMethod="GetCompletionList"        ServicePath="AutoComplete.asmx" TargetControlID="txtQuery" BehaviorID="AutoCompleteEx"> 
</asp:AutoCompleteExtender>

6.    Add an AutoComplete.asmx and put the following code. It use Microsoft Enterprise Library (Microsoft.Practices.EnterpriseLibrary.Data.dll) to get the data access. So, we nee to add .dll to bin folder.

using System.Data;
using Microsoft.Practices.EnterpriseLibrary.Data;
[System.Web.Script.Services.ScriptService]
public class AutoComplete : System.Web.Services.WebService
{
private Database getDBConn()
        {
//To get sql connection.
            Database sqlDB = DatabaseFactory.CreateDatabase("sqlConn");
            return sqlDB;
        }
        [WebMethod]
        public string[] GetCompletionList(string prefixText)
        {
            DataSet ds = null;
            List<string> items = new List<string>(50);
            try
            {
                Database DB = getDBConn();
                ds = DB.ExecuteDataSet("GetProductsWithPrefix", prefixText);

                for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
                {
                    items.Add(ds.Tables[0].Rows[i][0].ToString());
                }
            }
            catch (Exception ex)
            {
                items = null;
            }
            return items.ToArray();
        }
}

7.    Add the Sql server connection in web.config look like below. We use "Northwind" database and it depends on your server setting.

<connectionStrings>
    <add name="sqlConn" connectionString="Data Source=.\SQLEXPRESS;Initial Catalog=Northwind;User ID=sa;Password=sa@sa"
      providerName="System.Data.SqlClient" />
  </connectionStrings>

8.    Add the following stored procedure into “Northwind” database.

USE [Northwind]
GO
CREATE PROCEDURE [dbo].[GetProductsWithPrefix]
    @keyword nvarchar(100)
AS
BEGIN
 SELECT TOP 50 ProductName  FROM Products WHERE ProductName LIKE @keyword + '%' ORDER BY ProductID DESC
END

By default, the AutoCompleteExtender will not display suggestions until after you have typed at least 3 characters. I changed  this default behavior by modifying the AutoCompleteExtender MinimumPrefixLength property.


More detail about AutoCompleteExtender :
http://www.asp.net/ajaxLibrary/AjaxControlToolkitSampleSite/AutoComplete/AutoComplete.aspx

Saturday, January 28, 2012

How to stop ASP.NET Development Server after stopping the solution.

When we run the very big solution, asp.net icon is still in system tray even after stopping that solution (ASP.NET Development Server is running behind scene). It is very tedious to close the icon one by one.  Don’t be worry. The way to solve is simple and we have to use macros in Visual Studio.


To create the macros, Open the Visual Studio and go to Tools Menu > Macros > Macros IDE, otherwise use short cut key Alt+F11. You see IDE as below.

Visual Studio Macros IDE
On Visual Studio Macros, go to MyMacros Project > EnvironmentEvent Module and create DebuggerEvents_OnEnterDesignMode event as below.
Private Sub DebuggerEvents_OnEnterDesignMode(ByVal Reason As EnvDTE.dbgEventReason) Handles DebuggerEvents.OnEnterDesignMode
        For Each p In System.Diagnostics.Process.GetProcesses
            If p.ProcessName.IndexOf("WebDev.WebServer40") > -1 Then
                p.Kill()
            End If
        Next
End Sub

That’s is all you have to do. Right now, you don’t need to worry about it. Just mouse over the asp.net icons.:)

How to make QR codes that can be scanned by a mobile phone.


A QR code (Quick Response code) is a type of matrix barcode (or two-dimensional code) first designed for the automotive industry. More recently, the system has become popular outside of the industry due to its fast readability and large storage capacity compared to traditional UPC barcodes. The code consists of black modules arranged in a square pattern on a white background. The information encoded can be text, URL or other data - like in the pages of magazines, in advertisements and even on TV and Web sites, and is readable by dedicated QR barcode readers and camera phones. You can make a QR code to link to your website, your email address or something else.
Structure of a QR code, highlighting functional elements
QR code has been used and printed on Chinese train tickets since late 2009.
 It is quite easy to make the QR code and short url as well. Popular URL shortener Bit.ly automatically creates QR codes for every URL. In order to see QR code, simply add “.qr” at the end of your shortened URL. Another one is qr.net and I used it for my web site.

Google’s URL shortener, goo.gl, can also do the same and more – you can see the QR created for every URL and traffic sources in the statics page.




To scan the QR, you need QR app. If you have a smart phone, go to the App store and search for a QR code reader. You’ll find several free apps. Run the App and then hold your phone’s camera over a QR code to read it. For iPhone 4s, I use QR Reader from here. It is quite easy and effective.

Now, it is time to make QR code for your business.

More about QR code : http://en.wikipedia.org/wiki/QR_code

Sunday, January 22, 2012

How to fix "The Remote server returned an error :(407) Proxy Authentication Required".

When your network use a proxy server for your LAN, you got the error for running the web application as below.
Error : The Remote server returned an error :(407) Proxy Authentication Required.

At that time, go Tools Menu> Internet Options> Connections Tab> LAN Settings and see Proxy Server information as below.


Add the following section to web.config.
<system.net>
    <defaultProxy enabled="true" useDefaultCredentials="true">
       <proxy  bypassonlocal="True" proxyaddress="http://webproxy:80/>
    </defaultProxy>
</system.net>

That's it. How's easy!


Tuesday, January 3, 2012

How to show Modal Dialog Boxes with .Net Ajax

With Microsoft® ASP.NET AJAX, dialog boxes are especially important for displaying context-sensitive information without a page reload or new page. It is therefore important to devise a different implementation of dialog boxes that are as effective as modal popups but hassle-free for users.
The ModalPopup extender takes the markup generated by a server-side ASP.NET panel and shows or hides it as the user clicks on an associated HTML element. Initially styled as hidden, the dialog box is downloaded onto the client when the page is loaded and then shown or hidden on demand.
The following example show Modal Dialog popup to edit the customer information as below :




First of all, you need to add AjaxControlToolKit.dll to References like look:










Here is Stylesheet and Javascript to add <head> tag.
<style type="text/css">
    .modalPopup
    {
        background-color: #ffffdd;
        border-width: 3px;
        border-style: solid;
        border-color: Gray;
        padding: 3px;
        width: 350px;
    }
    .modalBackground
    {
        background-color: Gray;
        filter: alpha(opacity=70);
        opacity: 0.7;
    }
</style>
<script type="text/javascript">
    function ok(sender, e) {
        $find('ModalPopupExtender1').hide();
        __doPostBack('editBox_OK', e);
    }
    function cancel(sender, e) {
        $find('ModalPopupExtender1').hide();
    }
    function pageLoad(sender, args) {
    //Note that the OnKeyPress event handler will not work unless you register it with the Microsoft AJAX     //Library. The best place to run this registration code is the pageLoad function, like so:
        $addHandler(document, "keydown", onKeyDown);
    }
    function onKeyDown(args) {
        //Closing the Popup Using the Esc Key
        if (args.keyCode == Sys.UI.Key.esc) {
            $find('ModalPopupExtender1').hide();
        }
    }
</script>


Here is server controls in .aspx page.
<form id="form1" runat="server">
    <asp:ScriptManager ID="ScriptManager1" runat="server"/>
    <div>
        <!--Using Partial Rendering to Update the Customer View -->
        <asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
            <ContentTemplate>
                <table>
                    <tr>
                        <td><b>Customer ID:</b></td>
                        <td><asp:Label runat="server" ID="lblCustomerID" Text="C00001"/></td>
                    </tr>
                    <tr>
                        <td><b>Company Name:</b></td>
                        <td><asp:Label runat="server" ID="lblCompanyName" Text="Eastern Connection"/></td>
                    </tr>
                    <tr>
                        <td><b>Contact Name:</b></td>
                        <td><asp:Label runat="server" ID="lblContactName" Text="Ann Devon"/></td>
                    </tr>
                    <tr>
                        <td><b>Country:</b></td>  
                        <td><asp:Label runat="server" ID="lblCountry" Text="Germany"/></td>
                    </tr>
                     <tr>
                        <td>
                            <asp:Button runat="server" ID="btnEditText" Text="Edit text" OnClick="btnEditText_Click" />
                        </td>
                        <td>
                        </td>
                    </tr>
                </table>
            </ContentTemplate>
            <Triggers>
                <asp:AsyncPostBackTrigger ControlID="editBox_OK"/>
            </Triggers>
        </asp:UpdatePanel>
    </div>
    <div>
        <asp:Button runat="server" ID="hiddenTargetControlForModalPopup" Style="display: none" />           <!-- Dialog box:: Edit customer info -->
        <!--The Content of a Modal Popup Supports Partial Rendering -->
        <asp:Panel ID="pnlEditCustomer" runat="server" CssClass="modalPopup" style="display:none;">
            <div style="margin:10px">
            <asp:UpdatePanel runat="server" ID="ModalPanel1" RenderMode="Inline" UpdateMode="Conditional">
                <ContentTemplate>
                <table>           
                    <tr>
                        <td><b>Customer ID:</b></td>
                        <td><asp:Label runat="server" id="editCustomerID" />
                        </td>
                    </tr>           
                    <tr>
                        <td><b>Company Name:</b></td>
                        <td><asp:TextBox runat="server" id="editTxtCompanyName" /></td>
                    </tr>
                    <tr>
                        <td><b>Contact Name:</b></td>
                        <td><asp:TextBox runat="server" id="editTxtContactName" /></td>
                    </tr>
                    <tr>
                        <td><b>Country:</b></td>
                        <td><asp:TextBox runat="server" id="editTxtCountry" /></td>
                    </tr>
                </table>  
                <hr />
                <asp:Button ID="btnApply" runat="server" Text="Apply" width="50px" OnClick="btnApply_Click"/>
                </ContentTemplate>
                </asp:UpdatePanel>             
                <asp:Button ID="editBox_OK" runat="server" Text="OK" width="50px"
                    onclick="editBox_OK_Click"/>
                <asp:Button ID="editBox_Cancel" runat="server" Text="Cancel" width="50px" />
            </div>
        </asp:Panel>
    </div>
    <div>
        <asp:ModalPopupExtender ID="ModalPopupExtender1" runat="server" 
            TargetControlID="hiddenTargetControlForModalPopup"
            PopupControlID="pnlEditCustomer"
            BackgroundCssClass="modalBackground"
            DropShadow="false"
            OkControlID="editBox_OK"
            OnOkScript="ok()"
            OnCancelScript="cancel()"
            CancelControlID="editBox_Cancel" />
    </div>
</form>

Add the following to code-behind.
protected void btnEditText_Click(object sender, EventArgs e)
{
    // Initialize the controls in the panel used as the UI of the dialog box
    InitDialog();

    // The panel markup has been served already to the page. To edit it,
    // you need to a) wrap the panel's content in an UpdatePanel region and
    // b) update the panel once you made any changes
    ModalPanel1.Update();

    // Order to inject the script to show the dialog as the page loads up
    // in the browser.
    ModalPopupExtender1.Show();
}
protected void InitDialog()
{
    editCustomerID.Text = lblCustomerID.Text;
    editTxtCompanyName.Text = lblCompanyName.Text;
    editTxtContactName.Text = lblContactName.Text;
    editTxtCountry.Text = lblCountry.Text;
    SetFocus("editTxtCompanyName");
}
protected void btnApply_Click(object sender, EventArgs e)
{
    // Edit the server controls in the modal panel. Because the
    // call occurs over a partial rendering call, any updates
    // will be automatically reflected by the client UI.
    if (editTxtCountry.Text == "Germany")
        editTxtCountry.Text = "Cuba";
    else
        editTxtCountry.Text = "USA";
}
protected void editBox_OK_Click(object sender, EventArgs e)
{
    // Save to the database
    // Refresh the UI
    lblCompanyName.Text = editTxtCompanyName.Text;
    lblContactName.Text = editTxtContactName.Text;
    lblCountry.Text = editTxtCountry.Text;
}

That's it. Develope on the trend!

Original Post : http://msdn.microsoft.com/en-us/magazine/cc164247.aspx

ModalPopup Demonstration : 
http://www.asp.net/ajaxLibrary/AjaxControlToolkitSampleSite/ModalPopup/ModalPopup.aspx

Note : Don't forget to add EnableEventValidation="false" to the 'page' directive.



Monday, January 2, 2012

How to download image from a web site programatically using HttpWebRequest

I was working on adding new features to Car Pass application. The new feature will show some details about the car accident and one of the details is showing map image associated with car accident event. To get that, I have developed an image service that downloads the map images(Google Static Map see here) in the background. This is done using HttpWebRequest object to send request to image URL with parameter. Following code shows you how you can download an image from a Url programatically using HttpWebRequest.

Create .aspx page and put the following code in code-behind.
protected void Page_Load(object sender, EventArgs e)
{
    //Here should be your image url.
    String url = "http://maps.googleapis.com/maps/api/staticmap?center=huamark,bangkapi,th&zoom=15&size=500x500&scale=1&format=jpg&maptype=roadmap&language=en&markers=icon:http://www.iblogseeker.com/favicon.ico|13.758185,100.628732&sensor=false";

    HttpWebRequest webRequest = HttpWebRequest.Create(url) as HttpWebRequest;
    HttpWebResponse resp = webRequest.GetResponse() as HttpWebResponse;
    if (resp.StatusCode == HttpStatusCode.OK)
    {
        if (resp.ContentType.Contains("image/"))
        {
            int pos = resp.ContentType.IndexOf("/");
            string fileName = string.Format("{0}.{1}", "Map", resp.ContentType.Substring(pos + 1));
            byte[] imageContent = ProcessImageStream(resp);

            MemoryStream ms = new MemoryStream(imageContent);
            System.Drawing.Image img = System.Drawing.Image.FromStream(ms);
            string path = string.Format(@"G:\{0}", fileName);
            img.Save(path);

            //for image manipulation with third party component such as Telerik Reporting, Bitmap is better.
            //e.g. when you rotate image and put in Telerik Report as image.
            System.Drawing.Bitmap bmap= new Bitmap(ms);
            bmap.RotateFlip(RotateFlipType.Rotate90FlipXY);
            bmap.Save(string.Format(@"G:\B{0}", fileName));
        }
    }
}

Here is utility function called from Page_Load.
private static byte[] ProcessImageStream(HttpWebResponse resp)
{
    byte[] streamContent;
    MemoryStream memStream = new MemoryStream();
    const int BUFFER_SIZE = 4096;
    int iRead = 0;
    Int64 iSize = 0;
    memStream.SetLength(BUFFER_SIZE);
    try
    {
        using (memStream)
        {
            while (true)
            {
                iRead = 0;
                byte[] respBuffer = new byte[BUFFER_SIZE];
                iRead = resp.GetResponseStream().Read(respBuffer, 0, BUFFER_SIZE);
                if (iRead == 0)
                {
                    break;
                }
                iSize += iRead;
                memStream.SetLength(iSize);
                memStream.Write(respBuffer, 0, iRead);
            }
            streamContent = memStream.ToArray();
        }
    }
    catch (Exception ex)
    {
        throw ex;
    }
    return streamContent;
}

When you run the application, it download image and save two images in drive G:.

Sunday, December 25, 2011

ASP.NET Gridview with custom paging and sorting.

When displaying large amounts of data it's often best to only display a portion of the data, allowing the user to step through the data ten or so records at a time. Additionally, the end user's experience can be enhanced if they are able to sort the data by one of the columns.
While default paging was easy to implement, it carried with it a performance cost since all records to be paged through were being returned from the database. That is, if the DataGrid was paging through a total of 1,000 records, showing 10 records per page, on each and every page request all 1,000 records would be returned from the database, but only the 10 appropriate ones would be displayed.
Custom paging solved this performance issue by requiring the page developer to tell the DataGrid exactly how many total records were being paged through as well as returning the precise subset of records to display on the page. The following example use ObjectDataSource for DAL and Microsoft.Practices.EnterpriseLibrary.Data.dll to shorten code.

//Here is server control.
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" CellPadding="4"
    AllowPaging="True" AllowSorting="True" AlternatingRowStyle-Wrap="True"
    DataSourceID="ObjectDataSource1" EmptyDataText="There is no data.">
    <RowStyle BackColor="#EFF3FB" />
    <Columns>
        <asp:BoundField HeaderText="No." DataField="No" />
        <asp:BoundField HeaderText="CustomerID" DataField="CustomerID" SortExpression="CustomerID"/>
        <asp:BoundField HeaderText="CompanyName" DataField="CompanyName" SortExpression="CompanyName" />
        <asp:BoundField HeaderText="ContactName" DataField="ContactName" SortExpression="ContactName" />
        <asp:BoundField HeaderText="ContactTitle" DataField="ContactTitle" SortExpression="ContactTitle" />
    </Columns>
    <AlternatingRowStyle BackColor="White" />
</asp:GridView>
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server" SelectMethod="GridDataPage"
    TypeName="DAL" SelectCountMethod="DataRowCount"
    SortParameterName="SortExpression" EnablePaging="True">
    <SelectParameters>
        <asp:Parameter Name="maximumRows" Type="Int32" />
        <asp:Parameter Name="startRowIndex" Type="Int32" />
        <asp:Parameter Name="SortExpression" Type="String" />
    </SelectParameters>
</asp:ObjectDataSource>

//Here is the connection string in web.config and it use sample "Northwind" db and "Customers" table.
<connectionStrings>
    <add name="sqlConn" providerName="System.Data.SqlClient"  connectionString="Server='.\SQLEXPRESS';uid='xxxxxx';pwd='xxxxxxxx';Database='Northwind';Pooling=False;"/>
</connectionStrings>

//Here is the underlying DAL class for ObjectDataSource.
using System.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Data;
public class DAL
{
    // Methods
    private static Database getDatabase()
    {
        Database database = null;
        try
        {
            database = DatabaseFactory.CreateDatabase("sqlConn");
        }
        catch (Exception ex)
        {
            //handle exception here.
        }
        return database;
    }
    public static DataSet GridDataPage(int maximumRows, int startRowIndex, string SortExpression)
    {
        DataSet ds = new DataSet();
        if (startRowIndex >= maximumRows)
        {
            startRowIndex++;
        }
        try
        {
            ds = getGridData(maximumRows, startRowIndex, SortExpression);
            if (ds != null && ds.Tables[0].Rows.Count > 0)
            {
                startRowIndex = (startRowIndex > 0) ? startRowIndex : 1;
                for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
                {
                    ds.Tables[0].Rows[i][0] = Convert.ToString((int)(i + startRowIndex));
                }
                HttpContext.Current.Items["rowCount"] = Convert.ToInt32(ds.Tables[1].Rows[0][0].ToString());
                return ds;
            }
            HttpContext.Current.Items["rowCount"] = 0;
        }
        catch (Exception ex)
        {
            //handle exception here.
        }
        return ds;
    }
    public static DataSet getGridData(int maximumRows, int startRowIndex, string SortExpression)
    {
        DataSet ds = new DataSet();
        try
        {
            ds = getDatabase().ExecuteDataSet("GetCustomers", new object[] { maximumRows, startRowIndex, SortExpression });
        }
        catch (Exception ex)
        {
            ds = null;
            //handle exception here.
        }
        return ds;
    }
    public static int DataRowCount(int maximumRows, int startRowIndex, string SortExpression)
    {
        return (int)HttpContext.Current.Items["rowCount"];
    }
}

//Here is transact-sql.
USE [Northwind]
GO
ALTER PROCEDURE [dbo].[GetCustomers]
    @pageSize INT = NULL,
    @pageStart INT = NULL,
    @orderBy nvarchar(200) = NULL
AS
BEGIN

DECLARE @sqlPopulate VARCHAR(2000)
IF @pageSize IS NULL or @pageSize = 0
    SET @pageSize = 10;
IF @pageStart IS NULL
    SET @pageStart = 0;
IF @orderBy IS NULL OR @orderBy = ''
    SET @orderBy = 'CustomerID DESC';
IF @pageStart = 0
BEGIN
    SET @sqlPopulate = 'SELECT '' '' AS No, CustomerID, CompanyName, ContactName, ContactTitle ' +
        + ' FROM dbo.Customers WHERE CustomerID IN '+
        '(SELECT top '+ CAST(@pageSize AS VARCHAR(10)) +' CustomerID FROM dbo.Customers ';

    SET @sqlPopulate = @sqlPopulate + ' ORDER BY ' + @orderBy +
        ') ORDER BY ' + @orderBy;
END
ELSE
BEGIN
    SET @sqlPopulate = 'SELECT '' '' AS No, CustomerID, CompanyName, ContactName, ContactTitle ' +
        ' FROM Customers WHERE CustomerID IN '+
        '(SELECT top '+ CAST(@pageSize AS VARCHAR(10)) + ' CustomerID FROM Customers WHERE CustomerID NOT IN '+
            '(SELECT top '+ CAST((@pageStart-1) AS VARCHAR(10)) +' CustomerID FROM Customers ';

    SET @sqlPopulate = @sqlPopulate + ' ORDER BY ' + @orderBy +
            ') ORDER BY ' + @orderBy + ') ORDER BY ' + @orderBy;
END
EXEC(@sqlPopulate)

SET @sqlPopulate = '';
SET @sqlPopulate = 'SELECT COUNT(*) FROM Customers';
EXEC (@sqlPopulate)
END 

Useful link:
http://msdn.microsoft.com/en-us/library/ff632023.aspx

http://msdn.microsoft.com/en-us/library/aa479347.aspx

That's it. Enjoy!