Wednesday, September 16, 2009

Client validation gridview ASP.NET

I am going to explain the GridView Control Client Side (Javascript) Validation instead of server side validation controls.

I have a asp.net gridview which have three textboxes and two dropdownlist fields.Following screen shot showing that.



I am checking product code exists or not in database on onblur event




protected void grdBookinStock_RowDataBound(object sender, GridViewRowEventArgs e)
    {
 TextBox txtProductCode = (TextBox)e.Row.FindControl("txtProductCode");
txtProductCode.Attributes.Add("Onblur", "IsProductCodeExist(this.value);");
}


Now Javascript method IsProductCodeExist:


  function IsProductCodeExist(txtProductCode) {
            if (txtProductCode != "") {
                var IsExistsValue = (AjaxFunctions.IsProductCodeExists(txtProductCode)).value;

                if (IsExistsValue == false)
                    alert('Product Code does not exists');
            }
        }


Html code for gridview:

<asp:GridView ID="grdBookinStock" BackColor="LightGoldenrodYellow" BorderColor="Tan"
                                BorderWidth="1px" CellPadding="2" ForeColor="Black" AutoGenerateColumns="False"
                                ShowFooter="True" runat="server" OnRowDataBound="grdBookinStock_RowDataBound">
                                <Columns>
                                    <asp:TemplateField HeaderText="Product Code">
                                        <ItemTemplate>
                                            <asp:TextBox ID="txtProductCode" runat="server" MaxLength="6"></asp:TextBox>
                                        </ItemTemplate>
                                    </asp:TemplateField>
                                    <asp:TemplateField HeaderText="Owner">
                                        <ItemTemplate>
                                            <asp:DropDownList ID="ddlOwner" runat="server" AutoPostBack="True" OnSelectedIndexChanged="ddlOwner_SelectedIndexChanged">
                                            </asp:DropDownList>
                                        </ItemTemplate>
                                    </asp:TemplateField>
                                    <asp:TemplateField HeaderText="Warehouse">
                                        <ItemTemplate>
                                            <asp:DropDownList ID="ddlWarehouse" runat="server" AutoPostBack="True" OnSelectedIndexChanged="ddlWarehouse_SelectedIndexChanged">
                                            </asp:DropDownList>
                                        </ItemTemplate>
                                    </asp:TemplateField>
                                    <asp:TemplateField HeaderText="Bin">
                                        <ItemTemplate>
                                            <asp:TextBox ID="txtBin" runat="server" MaxLength="12" Enabled="False"
                                             autocomplete="off" AutoCompleteType="Disabled"></asp:TextBox>
                                            <cc1:AutoCompleteExtender ID="AutoCompleteExtender1" runat="server" ServiceMethod="GetCompletionList"
                                                UseContextKey="True" MinimumPrefixLength="1" CompletionInterval="500" EnableCaching="false"
                                                CompletionSetCount="12" TargetControlID="txtBin">
                                            </cc1:AutoCompleteExtender>
                                            <cc1:FilteredTextBoxExtender ID="FilteredTextBoxExtender2" FilterType="Custom" ValidChars="1234567890-"
                                                TargetControlID="txtBin" runat="server">
                                            </cc1:FilteredTextBoxExtender>
                                        </ItemTemplate>
                                    </asp:TemplateField>
                                    <asp:TemplateField HeaderText="Quantity">
                                        <ItemTemplate>
                                            <asp:TextBox ID="txtQuantity" runat="server" MaxLength="8" Enabled="False"></asp:TextBox>
                                            <cc1:FilteredTextBoxExtender ID="FilteredTextBoxExtender1" FilterType="Numbers" TargetControlID="txtQuantity"
                                                runat="server">
                                            </cc1:FilteredTextBoxExtender>
                                        </ItemTemplate>
                                    </asp:TemplateField>
                                </Columns>
                                <FooterStyle BackColor="Tan" />
                                <PagerStyle BackColor="PaleGoldenrod" ForeColor="DarkSlateBlue" HorizontalAlign="Center" />
                                <SelectedRowStyle BackColor="DarkSlateBlue" ForeColor="GhostWhite" />
                                <HeaderStyle BackColor="Tan" Font-Bold="True" />
                                <AlternatingRowStyle BackColor="PaleGoldenrod" />
                            </asp:GridView>
                        </td>
                    </tr>
                    <tr>
                        <td>
                            &nbsp;
                            </td>
                        <td>
                            &nbsp;
                            <asp:Button ID="btnSave" runat="server" CssClass="control"
                                OnClick="btnSave_Click" OnClientClick="return ValidateData();" Text="Save" />
                            <asp:Button ID="btnCancel" runat="server" CssClass="control"
                                OnClick="btnCancel_Click" Text="Refresh" />
                        </td>
                    </tr>
</Table>


Now I am validate data on save button

Client side Javascript method ValidateData():

function ValidateData() {
            var grid = document.getElementById("<%= grdBookinStock.ClientID %>");
            var cellProductCode;
            var cellOwner;
            var cellWarehouse;
            var cellBin;
            var cellQuantity;
            var cellProductCodeValue;
            var cellOwnerValue;
            var cellWarehouseValue;
            var cellBinValue;
            var cellQuantityValue;
           
            if (grid.rows.length > 0) {
                //loop starts from 1. rows[0] points to the header.
                for (i = 1; i < grid.rows.length; i++) {

                    cellProductCode = grid.rows[i].cells[0];
                    cellOwner = grid.rows[i].cells[1];
                    cellWarehouse = grid.rows[i].cells[2];
                    cellBin = grid.rows[i].cells[3];
                    cellQuantity = grid.rows[i].cells[4];

                    for (j = 0; j < cellProductCode.childNodes.length; j++) {

                        //if childNode type is CheckBox

                        if (cellProductCode.childNodes[j].type == "text") {
                            cellProductCodeValue = cellProductCode.childNodes[j].value;
                            //alert(cellProductCodeValue);

                        }
                    }

                    for (j = 0; j < cellOwner.childNodes.length; j++) {

                        //if childNode type is CheckBox

                        if (cellOwner.childNodes[j].tagName == "SELECT") {
                            cellOwnerValue = cellOwner.childNodes[j].value;
                            // alert(cellOwnerValue);
                        }
                    }

                    for (j = 0; j < cellWarehouse.childNodes.length; j++) {



                        if (cellWarehouse.childNodes[j].tagName == "SELECT") {
                            cellWarehouseValue = cellWarehouse.childNodes[j].value;
                            //alert(cellWarehouseValue);
                        }
                    }

                    for (j = 0; j < cellBin.childNodes.length; j++) {



                        if (cellBin.childNodes[j].type == "text") {
                            cellBinValue = cellBin.childNodes[j].value;
                            //alert(cellBinValue);
                        }
                    }
                    for (j = 0; j < cellQuantity.childNodes.length; j++) {

                        if (cellQuantity.childNodes[j].type == "text") {
                            cellQuantityValue = cellQuantity.childNodes[j].value;
                            // alert(cellQuantityValue);
                        }
                    }

                    if (cellProductCodeValue != "" || cellOwnerValue != "0" || cellWarehouseValue != "" || cellBinValue != "" || cellQuantityValue != "") {
                        if (cellProductCodeValue == "")
                        { alert('Enter product code');return false; }
                        if (cellOwnerValue == "0") {
                            alert('Select owner.'); return false;
                        }
                        if (cellWarehouseValue == "0") {
                            alert('Select warehouse.'); return false;
                        }
                        if (cellBinValue == "") {
                            alert('Enter bin.'); return false;
                        }
                        if (cellQuantityValue == "") {
                            alert('Enter quantity.'); return false;
                        }


                    }
                    function SetWarehouseIdtoHdnField() {
                       var hdn =document.getElementById('ctl00_ContentPlaceHolder1_hdnWarehouseId')

                       AjaxFunctions.SetValueWarehouse(hdn.value);



                    }


                }
               
            }
            //return true;
            if (confirm("Are you sure, you want to save the data?")) {
                return true;
            }
            else {

                return false;
            }

        }




 

 If you feeling bother about AjaxFunctions then you can see my old post

http://rajendramalav.blogspot.com/2009/07/call-server-side-method-from-client.html

Monday, August 31, 2009

Custom SEO Friendly Paging Datalist ASP.NET

Recently I have implemented paging with the Asp.net Datalist .But according to my client this was not good for SEO purposes and send links to the customer by mail and other ways. So I have done lots of googling and implement paging in following way.
you can check asp.net Datalist Paging on following link

http://amberdev.rockschat.co.uk/GemCollector/






I have created a stored procedure that return paged result set.

ALTER Proc [dbo].[DatalistPaging]
@CategoriesString as varchar(5000),
@PageIndex int=0,
@PageSize int=10,
@Sort VARCHAR(100)=''
As
BEGIN



create table #DataList Paging (Description varchar(200)
,RRP decimal(10,4)
,WebPrice decimal(10,4)
,WebText varchar(200)
,LeadColour varchar(20)
,Prefix varchar(25)
,Gemstone varchar(50)
,CountryName varchar(20)
,CutName varchar(25)
,ShapeName varchar(30)
,Width decimal(6,2)
,[Length] decimal(6,2)
,Depth decimal(6,2)
,Colour varchar(35)
,Clarity varchar(30)
,Grade varchar(5)
,Quantity INT
,Carats decimal(10,4)
,Treatment int
,Calibrated bit
,ProductDetailID int
,ProductCode VARCHAR(10) )




DECLARE @Categories VARCHAR(100)



SET @Categories =RTRIM(LTRIM(@Categories))
INSERT INTO #DataList Paging (Description
,RRP
,WebPrice
,WebText
,LeadColour
,Prefix
,Gemstone
,CountryName
,CutName
,ShapeName
,Width
,[Length]
,Depth
,Colour
,Clarity
,Grade
,Quantity
,Carats
,Treatment
,Calibrated
,ProductDetailID
,ProductCode)

SELECT
ProductDetails.Description
,ProductDetails.RRP
,isnull(ProductDetails.WebPrice ,0) WebPrice
,ProductDetails.WebText
,CategoryLeadColour.LeadColourName AS LeadColour
,CategoryGemstoneVariation.Name as Prefix
,TypeStone.TypeName as Gemstone
,Country.CountryName
,CategoryCut.CutName
,CategoryShape.ShapeName
,ProductDetailGemstone.Width
,ProductDetailGemstone.[Length]
,ProductDetailGemstone.Depth --(if it is > 0)
,CategoryHue.HueName AS Colour
,ISNULL(CategoryClarity.Name,'') AS Clarity
,ISNULL(CategoryClarity.grade,'') as Grade
,ProductDetailGemstone.Quantity
,ProductDetailGemstone.Carats
,ProductDetailGemstone.Treatment
,ProductDetailGemstone.Calibrated
,ProductDetails.ProductDetailID
,ProductDetails.ProductCode


FROM ProductDetails
Inner join ProductDetailGemstone on ProductDetails.ProductDetailID=ProductDetailGemstone.ProductDetailId
LEFT JOIN CategoryShape on CategoryShape.ShapeId=Shape
LEFT JOIN CategoryCut on CategoryCut.CutId=Cut
LEFT OUTER JOIN Country On Country.CountryId = ProductDetailGemstone.Country
LEFT OUTER JOIN CategoryClarity ON CategoryClarity.Id = ProductDetailGemstone.Clarity
LEFT OUTER JOIN CategoryTreatment ON CategoryTreatment.Id = ProductDetailGemstone.Treatment
LEFT OUTER JOIN CategoryHue ON CategoryHue.HueId = ProductDetailGemstone.Colour
LEFT JOIN TypeStone on TypeStone.TypeId=ProductDetailGemstone.Gemstone
LEFT JOIN CategoryGemstoneVariation ON CategoryGemstoneVariation.id=ProductDetailGemstone.Variation
LEFT JOIN CategoryLeadColour ON CategoryLeadColour.LeadColourId=ProductDetails.LeadColour
WHERE CategoryShape.ShapeName =@Categories OR
CategoryCut.CutName = @Categories OR
TypeStone.TypeName = @Categories OR
CategoryGemstoneVariation.Name = @Categories
OR CategoryLeadColour.LeadColourName = @Categories


DECLARE @PageLowerBound int
DECLARE @PageUpperBound int
DECLARE @RowsToReturn int
-- First set the rowcount
SET @RowsToReturn = @PageSize * (@PageIndex + 1)
SET ROWCOUNT @RowsToReturn
-- Set the page bounds
SET @PageLowerBound = @PageSize * @PageIndex
SET @PageUpperBound = @PageLowerBound + @PageSize + 1
-- Create a temp table to store the select results
CREATE TABLE #PageIndex
(
IndexId int IDENTITY (1, 1) NOT NULL,
ProductDetailID int
)
-- Insert into the temp table
IF @Sort='sorthigh'
INSERT INTO #PageIndex (ProductDetailID)
SELECT ProductDetailID FROM #temp ORDER BY ISNULL(#temp.WebPrice,0) desc --#temp.ProductDetailID
ELSE IF @Sort='sortlow'
INSERT INTO #PageIndex (ProductDetailID)
SELECT ProductDetailID FROM #temp ORDER BY ISNULL(#DataList Paging.WebPrice,0)
ELSE
INSERT INTO #PageIndex (ProductDetailID)
SELECT ProductDetailID FROM #DataList Paging ORDER BY #DataList Paging.ProductDetailID

SELECT ProductCode,
dbo.RoundCaratsWt(Carats) as Carats
,Prefix,Gemstone,Description,RRP
,Convert(decimal(10,2),ISNULL(WebPrice,0)) WebPrice
,WebText
,LeadColour
,CountryName AS Country
,CutName AS Cut
,ShapeName As Shape
,Width
,[Length]
,Depth
,Colour
,Clarity
,Grade
,Quantity
,Treatment
,Calibrated
,#DataList Paging.ProductDetailID
FROM #DataList Paging , #PageIndex PageIndex
WHERE #DataList Paging.ProductDetailID = PageIndex.ProductDetailID AND PageIndex.IndexID > @PageLowerBound AND PageIndex.IndexID < @PageUpperBound ORDER BY PageIndex.IndexID Declare @NoofRows INT Declare @NoofPages INT Select @NoofRows=COUNT(1) FROM #DataList Paging --SET @NoofPages = @NoofRows/@PageSize +1 return @NoofRows END

Now call this Stored procedure and get Dataset to populate records to Asp.net datalist Paging in following way:


public DataTable Get_Datalist_Paging (out int intNoofPage) {
string strConn = GlobalDAL.GetConnection();
try
{
SqlParameter[] paramsToStore = new SqlParameter[5]; paramsToStore[0] = new SqlParameter("@CategoriesString", SqlDbType.VarChar);
paramsToStore[0].Value = CategoriesString;
paramsToStore[0].Size = 5000;
paramsToStore[1] = new SqlParameter("@PageIndex", SqlDbType.Int);
paramsToStore[1].Value = PageIndex;
paramsToStore[2] = new SqlParameter("@PageSize", SqlDbType.Int);
paramsToStore[2].Value = PageSize;
paramsToStore[3] = new SqlParameter("@Sort", SqlDbType.VarChar);
paramsToStore[3].Value = Sort;
paramsToStore[4] = new SqlParameter("Return_Value", SqlDbType.Int);
paramsToStore[4].Direction = ParameterDirection.ReturnValue; DataSet ds = SqlHelper.ExecuteDataset(strConn, CommandType.StoredProcedure, "Gem_GetProductsFromCategories", paramsToStore);
intNoofPage = Convert.ToInt32(paramsToStore[4].Value);
return ds.Tables[0];

} catch (Exception excp)
{
throw excp;
}
}



Call following method on page_Load event to populate records to Asp.net datalist Paging --

DataTable objResult = objProducts.Get_Datalist_Paging(out intNoofRows);
public void BindList(DataTable dt)
{
try
{
dlstProductDetail.DataSource = dt;
dlstProductDetail.DataBind();
}
catch (Exception ex)
{
}
finally
{
dt = null;
}
}

private void UpdatePagingText()
{
if (pageIndex > 1 && pageIndex < intpage1 =" pageIndex" intpage2 =" pageIndex;" intpage3 =" pageIndex" pageindex ="=">= 3)
{
intPage1 = pageIndex - 2;
intPage2 = pageIndex - 1;
intPage3 = pageIndex;
}
else if (pageIndex == 1)
{
intPage1 = 1;
intPage2 = 2;
intPage3 = 3;
}
lbtn1.Text = intPage1.ToString();
lbtn1Bottom.Text = intPage1.ToString();
lbtn2.Text = intPage2.ToString();
lbtn2Bottom.Text = intPage2.ToString();
lbtn3.Text = intPage3.ToString();
lbtn3Bottom.Text = intPage3.ToString();

lbtn1.NavigateUrl = strapplicationurl + "Gemstones/" + strCategoryLogo + "/" + lbtn1.Text + "/" + strPageSetting + "/" + strPageSorting + "/" + strFilter;

lbtn1Bottom.NavigateUrl = strapplicationurl + "Gemstones/" + strCategoryLogo + "/" + lbtn1.Text + "/" + strPageSetting + "/" + strPageSorting + "/" + strFilter;
lbtn2.NavigateUrl = strapplicationurl + "Gemstones/" + strCategoryLogo + "/" + lbtn2.Text + "/" + strPageSetting + "/" + strPageSorting + "/" + strFilter;

lbtn2Bottom.NavigateUrl = strapplicationurl + "Gemstones/" + strCategoryLogo + "/" + lbtn2.Text + "/" + strPageSetting + "/" + strPageSorting + "/" + strFilter;
lbtn3.NavigateUrl = strapplicationurl + "Gemstones/" + strCategoryLogo + "/" + lbtn3.Text + "/" + strPageSetting + "/" + strPageSorting + "/" + strFilter;

lbtn3Bottom.NavigateUrl = strapplicationurl + "Gemstones/" + strCategoryLogo + "/" + lbtn3.Text + "/" + strPageSetting + "/" + strPageSorting + "/" + strFilter;

if (pageIndex < navigateurl =" strapplicationurl" navigateurl =" strapplicationurl" pageindex ="=" visible =" false;" visible =" false;"> 1)
{
lbtnPrev.NavigateUrl = strapplicationurl + "Gemstones/" + strCategoryLogo + "/" + (pageIndex - 1) + "/" + strPageSetting + "/" + strPageSorting + "/" + strFilter;
lbtnPrevBottom.NavigateUrl = strapplicationurl + "Gemstones/" + strCategoryLogo + "/" + (pageIndex - 1) + "/" + strPageSetting + "/" + strPageSorting + "/" + strFilter;
}
else if (pageIndex == 1)
{
lbtnPrev.Visible = false;
lbtnPrevBottom.Visible = false;
}

// ShowPageSettings();
}


Handling for above navigate url I have created a
HttpModule for url rewrite
-


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;

namespace GemsCollectorBAL.Categories
{
class CategoryModule : IHttpModule
{
public void Init(System.Web.HttpApplication context)
{
context.BeginRequest += new EventHandler(OnBeginRequest);
}
private void OnBeginRequest(object sender, EventArgs e)
{
string strCategrories = string.Empty;
string strPageIndex = string.Empty;
string strPageSetting = string.Empty;
string strSorting = string.Empty;
string strFilter = string.Empty;

int temp = 0;
HttpApplication app;
string requestUrl;

app = sender as HttpApplication;
requestUrl = app.Request.Url.ToString();




strCategrories += "PageIndex=" + strPageIndex + "&";
strCategrories += "PageSetting=" + strPageSetting + "&";
strCategrories += "PageSorting=" + strSorting + "&";
strCategrories += "Filter=" + strFilter ;

}
}

}


String strCurrentPath;
String strCustomPath;
strCurrentPath = app.Request.Path.ToLower();
if (strCurrentPath.IndexOf("/gemstones/") >= 0)
{
strCustomPath = "~/Categories/CategoryDetails.aspx?" + strCategrories;
// rewrite the URL
app.Context.RewritePath(strCustomPath);
}




}

public void Dispose()
{
}
}
}



Register this HttpModule to web.config to Rewrite Url:

 <httpModules>
    
      <add name="CategoryModule" type="GemsCollectorBAL.Categories.CategoryModule,GemsCollectorBAL"/>
          
    </httpModules>



UI Code Looks like in this way for
Asp.net Datalist Paging:




 <tr  id="trPaging" runat="server">
                <td class="topSubMenu">
                    <table cellpadding="0" cellspacing="0">
                        <tr>
                            <td style="width: 100px" id="tdPageof" runat="server" enableviewstate="false">
                                <b>Page
                                    <%=pageIndex %>
                                    of
                                    <%=Noofpages %>
                                </b>
                            </td>
                            <td id="tdPaging" runat="server" style="width: 425px">
                                <asp:HyperLink ID="lbtnPrev" runat="server" CssClass="topSubMenu"
                                    EnableViewState="False" >Previous</asp:HyperLink>
                                &nbsp;&nbsp;
                                <asp:HyperLink ID="lbtn1" runat="server" Visible="false" CssClass="topSubMenu" enableviewstate="false">1</asp:HyperLink>
                                &nbsp;&nbsp;
                                <asp:HyperLink ID="lbtn2" runat="server" Visible="false" CssClass="topSubMenu"  enableviewstate="false">2</asp:HyperLink>
                                &nbsp;&nbsp;
                                <asp:HyperLink ID="lbtn3" runat="server" Visible="false" CssClass="topSubMenu" enableviewstate="false">3</asp:HyperLink>
                                &nbsp;&nbsp;
                                <asp:HyperLink ID="lbtnNext" runat="server" CssClass="topSubMenu"
                                    EnableViewState="False" >Next</asp:HyperLink>&nbsp;&nbsp;&nbsp;
                                <asp:HyperLink ID="lbtnShowPaging" runat="server" CssClass="topSubMenu"
                                    EnableViewState="False"  >Show All</asp:HyperLink>
                            </td>
                            <td align="right">
                                <b>Sort By:</b>&nbsp;&nbsp;&nbsp;
                                <asp:HyperLink ID="lbtnHighestPrice" runat="server" CssClass="PagingLinks"
                                    EnableViewState="False">Highest price</asp:HyperLink>&nbsp;&nbsp;&nbsp;
                                <asp:HyperLink ID="lbtnLowestPrice" runat="server" CssClass="PagingLinks"
                                    EnableViewState="False">Lowest price</asp:HyperLink>
                            </td>
                        </tr>
                    </table>
                </td>
            </tr>
        </table>
        <div style="width: 800px">
            <asp:DataList ID="dlstProductDetail" runat="server" RepeatDirection="Horizontal"
                OnItemDataBound="dlstProductDetail_ItemDataBound" RepeatColumns="4"
                EnableViewState="False">
                <ItemTemplate>
                    <table class="ItemBorder" cellpadding="0" cellspacing="0" border="0">
                        <tr id="trTitle" runat="server"   EnableViewState="false">
                            <td align="left" class="ItemTop" colspan="2" runat="server" id="tdView" onserverclick="tdView_Click"  EnableViewState="false">
                           
                                    <asp:HyperLink ID="lbtnProductHeader" Width="100%" ForeColor="White"  NavigateUrl="" runat="server"  enableviewstate="false"></asp:HyperLink>
                            </td>
                         
                        </tr>
                        <tr>
                            <td colspan="2" align="center" style="padding-top: 5px">
                            
                                    <asp:HyperLink ID="imgProducts" ToolTip='<%# DataBinder.Eval(Container.DataItem, "ProductCode")%>' CssClass="ProductImage" runat="server" Height="100px" Width="100px"  enableviewstate="false"></asp:HyperLink>
                            </td>
                        </tr>
                        <tr>
                            <td valign="top">
                                <table cellpadding="0" cellspacing="0">
                                
                                </table>
                            </td>
                            <td align="right">
                             
                            </td>
                        </tr>
                    
                        <tr>
                            <td style="width: 20px">
                                &nbsp;
                            </td>
                            <td style="padding-top: 10px; width: *" align="right">
                                <span class="webprice" enableviewstate="false">£<%# DataBinder.Eval(Container.DataItem, "WebPrice")%></span>
                            </td>
                        </tr>
                      
                    </table>
                </ItemTemplate>
            </asp:DataList>
        </div>


Summary : So we can use this mechanism to all Asp.net binding controls.

Friday, July 17, 2009

ASP.NET Performance Improvement Techniques(GZIP)

Now a days lot of web applications have many performance issues. We can easily come out these by implementing some techniques. One of them GZip compression is very important.


The beauty of this new GZip support is how easy it is to use in your own ASP.NET code. For example the the cached RSS feed is GZip encoded which uses GZipStream on the Response.OutputStream fed to an XmlWriter():



Response.ContentType = "text/xml";



Stream Output = Response.OutputStream;



if (Westwind.Tools.wwWebUtils.IsGZipSupported())

{

GZipStream gzip = new GZipStream(Response.OutputStream, CompressionMode.Compress);

Response.AppendHeader("Content-Encoding", "gzip");

Output = gzip;

}



Encoding Utf8 = new UTF8Encoding(false); // No BOM!

XmlTextWriter Writer = new XmlTextWriter(Output,Utf8);



Writer.Formatting = Formatting.Indented;



Writer.WriteStartElement("rss");







Writer.WriteEndElement(); // rss



Writer.Close();

Response.End();





GZipStream is a stream acts like a stream filter so you can assign it to an existing stream like ResponseStream can intercept all inbound data then write the updated data into the actual Response stream. It’s super easy to do.



You should always check however if GZip is enabled which is done by this helper method IsGZipSupported() which looks like this:



///

/// Determines if GZip is supported

///


///

public static bool IsGZipSupported()

{

string AcceptEncoding = HttpContext.Current.Request.Headers["Accept-Encoding"];

if (!string.IsNullOrEmpty(AcceptEncoding) &&

AcceptEncoding.Contains("gzip") || AcceptEncoding.Contains("deflate") )

return true;

return false;

}



This ensures that you don’t encode content when the client doesn’t understand GZip and would be unable to read the encoded GZip content. Note that the code checks for either gzip or deflate so this assumes before encoding you’ll pick the right encoding algorithm.

GZip in Page Content

Speaking of encoding - above was XML and raw ResponseStream encoding, but you can also apply GZip content very, very easily to your page level or any ASP.NET level code (such as in an HTTP handler). In fact, you can use a very generic mechanism to encode any output by using a Response.Filter which the following helper method (also in wwWebUtils) demonstrates:



///
/// Sets up the current page or handler to use GZip through a Response.Filter
/// IMPORTANT:
/// You have to call this method before any output is generated!
///

public static void GZipEncodePage()
{
HttpResponse Response = HttpContext.Current.Response;

if (IsGZipSupported())
{
string AcceptEncoding = HttpContext.Current.Request.Headers["Accept-Encoding"];
if (AcceptEncoding.Contains("deflate"))
{
Response.Filter = new System.IO.Compression.DeflateStream(Response.Filter,
System.IO.Compression.CompressionMode.Compress);
Response.AppendHeader("Content-Encoding", "deflate");
}
else
{
Response.Filter = new System.IO.Compression.GZipStream(Response.Filter,
System.IO.Compression.CompressionMode.Compress);
Response.AppendHeader("Content-Encoding", "gzip");
}
}

// Allow proxy servers to cache encoded and unencoded versions separately
Response.AppendHeader("Vary", "Content-Encoding");
}



You can now take this helper function and use this in page level code. For example, the main page in my blog which is HUGE (frequently around 500k) uses it like this:



protected void Page_Load(object sender, EventArgs e)

{

wwWebUtils.GZipEncodePage();



Entry = WebLogFactory.GetEntry();



if (Entry.GetLastEntries(App.Configuration.ShowEntryCount, "pk,Title,Body,Entered,Feedback,Location") < 0)

throw new ApplicationException("Couldn't load WebLog Entries: " + Entry.ErrorMessage);



this.repEntries.DataSource = this.Entry.EntryList;

this.repEntries.DataBind();

}



That’s it. One line and the page will now conditionally GZip encode if the client supports it.



If you really wanted to you can take this even one step further and create a module that automatically sets the Response.Filter early in the pipeline and based on that automatically compresses all content.



However, remember GZip encoding applies compression on the fly so there’s some overhead in the GZip encoding – you are basically adding more CPU processing to your content to reduce the output size. If your content is not that large to start with there’s probably not that much sense in compressing in the first place so I don’t think that whole-sale compression of dynamic content is a good idea.


Caching

But one thing that can mitigate the overhead of GZip compression is caching.



both the RSS feed and the home page are usually heavily cached – the content doesn’t change all that frequently so there’s no reason to keep re-generating it right? If you use GZip on your content you have to be careful to cache both the GZipped content and the non-encoded content or else you’ll feed garbage to clients that don’t understand GZip.



So for example the default page has:



<%@ OutputCache Duration="60" VaryByParam="none" VaryByCustom="GZIP" %>



And then a custom Global.asax handler that looks like this:



public override string GetVaryByCustomString(HttpContext context, string custom)

{

if (custom == "GZIP")

{

if (Westwind.Tools.wwWebUtils.IsGZipSupported())

return "GZip";

return "";

}



return base.GetVaryByCustomString(context, custom);

}



Which results in possibly two different versions of the GZipped page being cached.



And there you have it - GZipped content is easy to create now in ASP.NET 2.0/.NET 2.0 and if judiciously applied it can save some significant bandwidth. On my homepage which is close to 500k of blog text content the GZipped size is 55k or so – nearly a 90% reduction in size. I’d say that’s plenty of worth it, especially when caching is added.

Delicious
Bookmark this on Delicious

Monday, July 6, 2009

Bind data to dropdownlist from client side javascript

var ddlFromWarehouseClientId = document.getElementById("ctl00_ContentPlaceHolder1_grdStockTransfer_ctl01_ddlFromWarehouse");

ddlFromWarehouseClientId.innerHTML = "";
var res1 = (AjaxFunctions.GetStockTranseferData()).value;
ddlFromWarehouseClientId.options.add(new Option("Select", "0", false, false));
var i = 0;
if (res1.Rows.length > 0) {
//CId.options.length = 0;
for (i = 0; i <= res1.Rows.length - 1; i++) {

ddlFromWarehouseClientId.options.add(new Option(res1.Rows[i].Name, res1.Rows[i].Id, false, false));
}
}



Name and Id are database field name

How to call ajax function from client side see my earlier post
http://rajendramalav.blogspot.com/2009/07/call-server-side-method-from-client

Call server side method from client script through Ajax

1.Create a class under App_Code folder

public class AjaxFunctions
{

[Ajax.AjaxMethod]
public bool IsNumber(int i)
{
if(i==1)
return true;
else
return false;
}
}


2.Register this class on page_load event of page

Ajax.Utility.RegisterTypeForAjax(typeof(AjaxFunctions));


3. Java script function
function OnChangeFromOwner() {
var res1 = (AjaxFunctions.IsNumber()).value;
}

Tuesday, June 30, 2009

Access image through url and render as jpeg in asp.net

class ImageProcessingModule : IHttpModule
{
public void Init(System.Web.HttpApplication context)
{
context.BeginRequest += new EventHandler(OnBeginRequest);
}
private void OnBeginRequest(object sender, EventArgs e)
{
HttpApplication app;
string requestUrl;

app = sender as HttpApplication;
requestUrl = app.Request.Url.ToString();
//requestUrl=requestUrl.Replace("https://", "http://");


//if (!requestUrl.ToLower().Contains("products")) { return; }
string[] strUrl = requestUrl.Split('/');
string ProductCode = string.Empty;
string Size = string.Empty;

for (int i = 0; i < strUrl.Length; i++)
{
if (strUrl[i].ToLower() == "images" && strUrl[i + 1].ToLower() == "products")
{
if ((i + 2) < strUrl.Length)
ProductCode = strUrl[i + 2];
if ((i + 3) < strUrl.Length)
Size = strUrl[i + 3];

string serverDirectory = app.Server.MapPath("~/UploadImages/" + Size);
string FilePath = System.IO.Path.Combine(serverDirectory, ProductCode) + ".jpg";
//app.Server.Transfer("~/ImageSystem/RetreiveImages.aspx?productcode=" + ProductCode + "&size=" + Size + "",false);
// app.Response.Redirect ("~/UploadImages/" + Size + "/" + ProductCode + ".jpg");

byte[] photo = null;
if (System.IO.File.Exists(FilePath))
{
photo = ReadImage(app.Server.MapPath( "~/UploadImages/" + Size + "/" + ProductCode + ".jpg"));//FilePath;
}
else
{
photo = ReadImage(app.Server.MapPath("~/UploadImages/" + Size + "/Missing.jpg"));//FilePath;

}
if (photo != null)
{
app.Response.ContentType = "image/jpeg";
app.Response.Cache.SetCacheability(HttpCacheability.Public);
app.Response.BufferOutput = false;
app.Response.OutputStream.Write(photo, 0, photo.Length);
}






}
}
// app.Response.Write(ProductCode+" hi "+ Size);

}

public void Dispose()
{
}
private static byte[] ReadImage(string p_postedImageFileName)
{
// bool isValidFileType = false;
try
{
FileInfo file = new FileInfo(p_postedImageFileName);


FileStream fs = new FileStream(p_postedImageFileName, FileMode.Open, FileAccess.Read);
BinaryReader br = new BinaryReader(fs);
byte[] image = br.ReadBytes((int)fs.Length);
br.Close();
fs.Close();
return image;

// return null;
}
catch (Exception ex)
{
return null;
//throw ex;
}
}
}

Web.Config settings
register http module



Thursday, May 28, 2009

Integrating BlogEngine into an existing website











Introduction to Blog Engine.Net -






BlogEngine.NET is open source .BlogEngine.NET is a full-featured blogging platform that is a breeze to set up, customize, and use. BlogEngine.NET works with your choice of data source; you may use SQL Server, or you may take the plug'n'play approach using XML files.

















  • Plug 'n' Play
    BlogEngine.NET is very easy to setup and customize. To make it work, just upload the files to an ASP.NET 2.0 webserver and you're ready to start writing. No database configuration, just plug'n'play.





  • Full Featured
    BlogEngine.NET comes with all the features you would expect from a modern blog engine as well as new unique features such as AJAX comments and screenshot trackbacks.





  • Web 2.0
    BlogEngine.NET features social bookmarks, OpenSearch support, XFN tags, AJAX, Microsummaries, Gravatars, coComments, tag cloud, Google sitemap and other so-called Web 2.0 features.





  • Cool Themes
    BlogEngine.NET comes with some very cool themes for you to choose from. If you want to modify or create a new theme you can do so easily with just a basic understanding of HTML and CSS.





  • XHTML Compliance
    All the controls in BlogEngine.NET are 100% XHTML 1.0 compliant. All posts you write automatically becomes compliant thanks to the tinyMCE text editor.





  • Extendable
    BlogEngine.NET is built from the ground up using nothing but C# and ASP.NET 2.0 all with simplicity in mind. It means that you can write new controls and themes by using the skills you already have as a .NET developer.





Above information about BlogEngine I have picked from http://www.asp.net/ website.I don't want to describe more about information regarding blog my concern only how to integrate it to existing website.






BlogeEngine support three kinds of membership providers-






We have to change setting in web.config according to your requirement .First of all change setting in custom section blogprovider .






<configSections>






<sectionGroup
name="BlogEngine">






<section
name="blogProvider"
requirePermission="false"
type="BlogEngine.Core.Providers.BlogProviderSection, BlogEngine.Core"
allowDefinition="MachineToApplication"
restartOnExternalChanges="true"/>






</sectionGroup>






</configSections>






<BlogEngine>






<blogProvider
defaultProvider="DbBlogProvider">






<providers>






<!--<add name="XmlBlogProvider" type="BlogEngine.Core.Providers.XmlBlogProvider, BlogEngine.Core"/>-->






<add
name="DbBlogProvider"
type="BlogEngine.Core.Providers.DbBlogProvider, BlogEngine.Core"
connectionStringName="BlogEngine" />






</providers>






</blogProvider>






</BlogEngine>






















  1. XmlMembershipProvider: - All data store in App_Data directory of Asp.net .so full rights must be applied on this folder.





    Web.Config setting –




































<membership
defaultProvider=" XmlMembershipProvider ">






<providers>






<clear/>






<add
name="XmlMembershipProvider"
type="BlogEngine.Core.Providers.XmlMembershipProvider, BlogEngine.Core"
description="XML membership provider"
passwordFormat="Hashed"/>












</providers>






</membership>












<roleManager
defaultProvider=" XmlRoleProvider"
enabled="true"
cacheRolesInCookie="true"
cookieName=".BLOGENGINEROLES">






<providers>






<clear/>






<add
name="XmlRoleProvider"
type="BlogEngine.Core.Providers.XmlRoleProvider, BlogEngine.Core"
description="XML role provider"/>












</providers>






</roleManager>






















  1. SqlMembershipProvider :- If your application using AspnetMembership then this option will be more useful.











    Web.Config setting –






























<membership
defaultProvider="SqlMembershipProvider">






<providers>






<clear/>






<add
name="SqlMembershipProvider"
type="System.Web.Security.SqlMembershipProvider"
connectionStringName="BlogEngine"
applicationName="BlogEngine"/>






</providers>






</membership>












<roleManager
defaultProvider="SqlRoleProvider"
enabled="true"
cacheRolesInCookie="true"
cookieName=".BLOGENGINEROLES">






<providers>






<clear/>






<add
name="SqlRoleProvider"
type="System.Web.Security.SqlRoleProvider"
connectionStringName="BlogEngine"
applicationName="BlogEngine"/>






</providers>






</roleManager>






















  1. DbMembershipProvider : - If your website using your on authentication using rather than aspnetmembership then this option will be best.











    Web.config settings :












<membership
defaultProvider="DbMembershipProvider">






<providers>






<clear/>






<add
name="DbMembershipProvider"
type="BlogEngine.Core.Providers.DbMembershipProvider, BlogEngine.Core"
passwordFormat="Clear"
connectionStringName="BlogEngine"/>






</providers>






</membership>












<roleManager
defaultProvider="DbRoleProvider"
enabled="true"
cacheRolesInCookie="true"
cookieName=".BLOGENGINEROLES">






<providers>






<clear/>






<add
name="DbRoleProvider"
type="BlogEngine.Core.Providers.DbRoleProvider, BlogEngine.Core"
connectionStringName="BlogEngine"/>






</providers>






</roleManager>












All of three them I want to describe DbMembershipProvider because other two no need to describe more here. lot of websites using own authentication mechanism so DbMembershipProvider will be best way to integration in my opinion.






Following changes should be made in BlogEngine.Core assembly:-






DB Provider classes are shown in following diagram:-































  1. Change table prefix in DbMembershipProvider.cs . Either set your table prefix or blank



































  1. Change table name and field name according to your database in DbMembershipProvider.cs class
























  2. Change table prefix , table name and field name according to your database in DbMembershipProvider.cs class





























  3. Define roles according to your database entries in web.sitemap


















    Summary:- BlogEngine.Net is best open source blog application that provide very simple integration providers






    We can also implement DBMebershipProvider for custom provider in our application.