Image in DetailsView

One of our forum members in MS Phil  has recently inquired if it's possible to display image from the database using a DetailsView control. Out of the box, it can't since the Imagefield rowfield only accepts a url for the image, but with the help of an auxilliary page we can.

Let's have our SqlDataSource setup first:

<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:HissDBConnectionString %>"

SelectCommand="SELECT [Emp_No], [First_Name], [Last_Name] FROM [HR_EmployeeMaster] WHERE Company=@Company">

<SelectParameters>

<asp:ControlParameter Name="Company" ControlID="DropDownList1" PropertyName="SelectedValue" />

</SelectParameters>

</asp:SqlDataSource>

I have a select statement which will query all employees depending on their company which will be selected on my Dropdownlist control.

Then our DetailsView control:

<asp:DetailsView ID="DetailsView1" runat="server" AutoGenerateRows="False" DataKeyNames="Emp_No"

DataSourceID="SqlDataSource1" Height="50px" Width="125px" AllowPaging="True">

<Fields>

 

 <asp:BoundField DataField="Emp_No" HeaderText="Emp_No" ReadOnly="True" SortExpression="Emp_No" />

 <asp:BoundField DataField="First_Name" HeaderText="First_Name" SortExpression="First_Name" />

<asp:BoundField DataField="Last_Name" HeaderText="Last_Name" SortExpression="Last_Name" />

</Fields>

</asp:DetailsView>

Now that we have our DetailsView up and running, it's time to make our auxilliary page; whose function will be the placeholder of our streamed image. Create another web page, let's name it DisplayImage.aspx.  In our code-behind and upon the Page_Load event we typed the following:

VB.NET:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load


Dim EmpNo As String= Request.QueryString("emp_no")
Dim commandString As String = "SELECT Photo FROM HR_EmpPhoto WHERE Emp_No= @empNo "
Using
myConn As New SqlConnection(ConfigurationManager.ConnectionStrings("HissDBConnectionString").ToString())
Dim myCommand As SqlCommand()
Dim myReader As SqlDataReader

myConn.Open()
myCommand = myConn.CreateCommand()
myCommand.Parameters.Add("@empNo",SqlDbType.Varchar,10) .Value = EmpNo
myReader = myCommand.ExecuteReader(CommandBehavior.CloseConnection)

 
If myReader.Read() Then

        Dim imgBuffer As Byte() = CType(myReader.Item("Photo"), Byte())

      Response.ContentType = "image/jpeg"
      Response.BinaryWrite(imgBuffer)

End If

   myConn.Close()

End Using

End Sub

 C#

protected void Page_Load(object sender, EventArgs e)

{

String empNo = Request.QueryString["emp_no"];
String commandString = "SELECT Photo FROM HR_EmpPhoto WHERE Emp_No=@empNo";

using (SqlConnection myConn = new SqlConnection (ConfigurationManager.ConnectionStrings["HissDBConnectionString"].ToString()))

{

    myConn.Open();
    SqlCommand
myCommand = myConn.CreateCommand();

    myCommand.Parameters.Add("@empNo",SqlDbType.Varchar,10) .Value = EmpNo

    SqlDataReader myReader = myCommand.EndExecuteReader(CommandBehavior.CloseConnection);

if (myReader.HasRows ()){
    byte[] imgBuffer = (byte[]) myReader["Photo"];
    Response.ContentType = "image/jpeg";
    Response.BinaryWrite (imgBuffer);
}

myConn.Close();

}

}

The query will try see if the there is a photo available for our employee. If it exists we then convert the content of our reader into a byte array so that we can pass it to our Response object's method BinaryWrite()  as an output stream. The content type should be properly configured so that the user agent(browser) knows how to deal with it, in case of our image, knows how to display it. However, I was testing it even with a wrong content type "image/gif" or no content type at all but the browser was able to display it correctly. Nevertheless, one should use the correct content type.

We can test our page by manually type at the address bar: http://localhost/ImageInDetailsView/DisplayImage.aspx?emp_no=7342. If the image is displaying then we proceed to add our ImageField row in our DetailsView.

Add the following as the first row of our DetailsView:

<asp:ImageField HeaderText = "Photo" DataImageUrlField="Emp_No"

DataImageUrlFormatString="~\DisplayImage.aspx?emp_no={0}">

<ControlStyle Width="150px" />

</asp:ImageField>

We are binding our DataImageUrlField to the Emp_No column from our datasource, from here we're going to get the parameter to pass to our auxilliary page. In our DataImageUrlFormatString we set it to our DisplayImage.aspx then pass in our querystring the parameter emp_no={0}, this tells the field to get the first column from our datasource so it depends on what column number you placed your bound column. We limit the size of our image to 150px only so that the display of picture is constant, no matter the size of the picture. The same technique can also be used in a GridView control.

That's all there is to it. Next time I'm going to show you how to do without the auxilliary page.

 UPDATED: Gavin noted that the code is open to sql-injection attack, so changed the code to a parameterized query. Thanks for pointing it out

Published 02-15-2006 3:16 AM by bonskijr
Filed under:

Comments

# re: Image in DetailsView

Thanks alot for this post
it took me pretty much all day to find out how to display a image in the imagefield of my gridview.

i would like to know how you can do it without having another webpage

cheers
mike

Monday, June 19, 2006 7:08 AM by Michael Galloway

# re: Image in DetailsView

This example is vulnerable to a SQL injection attack

Tuesday, August 08, 2006 12:16 AM by Gavin Joyce

# re: Image in DetailsView

Thanks for pointing that out, have updated it

Wednesday, August 09, 2006 5:19 AM by bonskijr