Wednesday, August 12, 2009

Generic Handlers to display images from database in a gridview from database.

Generic Handler ; A ‘Generic’ way to find the solution.

Was fuming my head to fetch the logo image from SQL Server database (Not the URL, Image stored as the type image, in binary format). Plenty of try outs could lead me in to the solution.

ASP.Net 2.0 does not allow images(binary format) from the database and directly databind to a control in the page. There are some tricky things to get it done, Take a sneak peak.

Here is my Company Master Table

Allow null I used as this field was an addition to the master table which has got references to the transactions. Hope you understood the significance of allowed null. Well, leave that topic, it doesn’t make any sense in this topic.

I had to deal with two presentation layer files for this scenario. One is the .aspx page where my grid view sits with data bound with all the company information, except the logo, and the other, an ASHX file to custom handle the request. Try binding the logo entity to the server side image control, its not gonna work out.

So bind all other fields of Company master to the grid’s item templates and see how the image can be displayed. Here comes the role of Generic Handler.

Generic Handlers are equivalent to custom handlers and they contain classes that fully implement IHttpHandler. All you need is to simply surf the Generic Handler (ASHX) files and they're compiled automatically just as ASPX file works.

Advantages of Generic Handlers

The advantage of using the generic handler is twofold. First, it's usually much more convenient to generate a simple handler than it is to create a whole new assembly to handle the request. Second, you don't need to run interference with either Web.Config or with IIS. That is, Web.Config and IIS already understand what to do about files with the extension of .ashx. Installing ASP.NET places those when mapping into IIS.

Limitations

However, ASHX files have the same limitations as ASPX and ASCX files in terms of their place in an ASP.NET project. Simple generic handlers go with the project. That is, for the handler to work, it must accompany the whole project. Alternatively, custom handlers deployed as separate assemblies may be deployed and shared among the enterprise as Global Assembly assemblies (that is, strongly named assemblies placed in the Global Assembly Cache).


Back to our problem; added an image control in the template field of the grid view where I had to load the Company Logo.Hope you know the way of creating a Generic Handler. If not follow these steps.
Right click on the Website Project and Add New item in the Solution Explorer of Visual Studio IDE.
My Stored Procedure fetches the image field from Company Master for a particular Company ID. This ID had to be provided from the Grid View’s Item template as a Query String to the Generic Handler.





No big deal, accepted the query string and passed it to Stored Procedure and fetch the data as byte[]. Did a binary write of the fetched data. From the ASPX page, ie, my Master Dot Net Page,

public void ProcessRequest (HttpContext context) {

SqlConnection con = new SqlConnection();
con.ConnectionString = ConfigurationManager.ConnectionStrings["MyConnString"].ConnectionString;
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "select CH_CMP_LOGO from CH_CMP_INFO where CH_CMP_ID = @ID";
cmd.CommandType = System.Data.CommandType.Text;
cmd.Connection = con;

SqlParameter ImageID = new SqlParameter("@ID", System.Data.SqlDbType.Int);
ImageID.Value = context.Request.QueryString["ID"];
cmd.Parameters.Add(ImageID);
con.Open();
SqlDataReader dReader = cmd.ExecuteReader();
dReader.Read();
context.Response.BinaryWrite((byte[])dReader["CH_CMP_LOGO"]);
dReader.Close();
con.Close();
}

I could browse and view the company listing.

Happy!





sorry, i forgot to tell about the data access layer specialty to fetch the image.

int logoImageIndex = reader.GetOrdinal("CH_CMP_LOGO");
if (!reader.IsDBNull(logoImageIndex))
{
companyListingEntity.LogoImage = new Byte[(reader.GetBytes(logoImageIndex, 0, null, 0, int.MaxValue))];
reader.GetBytes(logoImageIndex, 0, companyListingEntity.LogoImage, 0, companyListingEntity.LogoImage.Length);
}

No comments: