skip to Main Content

Is it possible to display the image?

The CategoryName was able to display fine,
but the CategoryImage displayed as array of byte

<asp:Repeater ID="Repeater1" runat="server">
   <ItemTemplate>
       <%#Eval("CategoryImage")%> <%#Eval("CategoryName")%>
   </ItemTemplate>
</asp:Repeater>
SqlDataReader dtrImage = cmdSelect.ExecuteReader();
Repeater1.DataSource = dtrImage;
Repeater1.DataBind();

Output:

Animal System.Byte[]
Food   System.Byte[]

2

Answers


  1. Not only is this possbible, but I fact recommend doing this.

    You can even do this for files as opposed to say the image in a database.
    (the reason why is security – you OFTEN don’t want files mapped to a folder that users can type in a URL to get say a PDF or whatever.

    So, you read the file, and stream it out.

    The nice part is any image, image button or whatever you place on the form can be sent the picture, and you don’t require some silly handler or "some other" place beyond the code.

    So, say we have a simple repeater like this

    (kind of card view layout).

    <asp:Repeater ID="Repeater1" runat="server" OnItemDataBound="Repeater1_ItemDataBound">
        <ItemTemplate>
            <div class="mybox">
                <div style="text-align: center; padding: 2px 10px 12px 10px">
                    <asp:Button ID="cmdMyView" runat="server" Text="View"
                        CssClass="btn-info" Style="float: right"
                        OnClick="cmdMyView_Click"
                        CommandArgument='<%# Eval("ID") %>' />
                    <br />
                    <h3><%# Eval("Fighter") %></h3>
                    <asp:Image ID="Image2" runat="server" Width="180" Height="120" />
                    <h4>Engine</h4>
                    <asp:Label ID="EngineLabel2" runat="server" Text='<%# Eval("Engine") %>' />
                    <h4>Description</h4>
                    <asp:Label ID="DescLabel" runat="server" Text='<%# Eval("Description") %>' />
                    <asp:CheckBox ID="chkSel" runat="server" Checked="false"
                        myid='<%# Eval("id") %>' />
    
                </div>
            </div>
        </ItemTemplate>
    </asp:Repeater>
    

    You note the image control in above.

    So, we have a image in the database.

    About the only requirement is of course you need to have saved in that database not only the file (as raw byte data), but you need the file extension.

    So, for above, we fill the repeater with this code:

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
            LoadGrid();
    }
    
    void LoadGrid()
    {
        using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
        {
            string strSQL = "SELECT * FROM Fighters";
            using (SqlCommand cmdSQL = new SqlCommand(strSQL, conn))
            {
                conn.Open();
                DataTable rstData = new DataTable();
                rstData.Load(cmdSQL.ExecuteReader());
                Repeater1.DataSource = rstData;
                Repeater1.DataBind();
            }
        }
    }
    

    So, that loads the repeater rather nice.

    So, the only part left is to fill out the image.

    In fact, this works even without a repeater anyway.

    So, for each "repeat", we need to pull the image from the database.

    So, in most cases, that means we use the row data bound event of the repeater.

    thus, this:

    protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
    {
        if ( (e.Item.ItemType == ListItemType.Item) ||  
            (e.Item.ItemType == ListItemType.AlternatingItem) )
        {
            Image ctlImage = (Image)e.Item.FindControl("Image2");
            DataRowView rData = (DataRowView)e.Item.DataItem;
            byte[] MyBytes = (byte[])rData["MyImage"];
            string MineType = MimeMapping.GetMimeMapping(rData["FileName"].ToString());
    
            rData["FileName"].ToString();
            ctlImage.ImageUrl =
                $@"data:{MineType};base64,{Convert.ToBase64String(MyBytes)}";
        }
    }
    

    And the result is now this:

    enter image description here

    And note how I have a button in the repeater. the code for that "view" button, as a example code is this:

        protected void cmdMyView_Click(object sender, EventArgs e)
        {
            Button btn = (Button)sender;
            RepeaterItem rRow = (RepeaterItem)btn.NamingContainer;
            int MyRowIndex = rRow.ItemIndex;
            int MyPK = Convert.ToInt32(btn.CommandArgument);
    
            Debug.Print("Row index click = " + MyRowIndex);
            Debug.Print("Pk data base = " + MyPK);
    
            // get say the engine from the row click
            Label lblEngine = (Label)rRow.FindControl("EngineLabel2");
            Debug.Print("engine = " + lblEngine.Text);
    

    That allows me to get the row index, the database PK, and even example code to pull one value out of that repeater.

    output:

    Row index click = 3
    Pk data base = 4
    engine = 1 × Pratt & Whitney F135-PW-100 afterburning turbofan
    

    Edit: Above only really great for a few SMALLER images

    So, often to just display a few thumb nails etc., then I do suggest just a stream out of the image from the database as a base64 string is fine.

    HOWEVER, and this is a big however:

    If you doing to display more then a few images, and you want that page to have post-backs (in place of say some link button to move on in the application), then as suggested in comments?

    Then, it near always BETTER to use + build a handler for this.

    This is especially if the repeater and web page in question will and does need post-backs. (if it does not, then turn off viewstate for the image control).

    So, a 2nd approach (and often the most common example). is thus to add a handler.

    So, the handler (add->new item->Generaic handler).

    So, that handler would look like this:

    public void ProcessRequest(HttpContext context)
    {
    
        int ImageID = 0;
        if (context.Request.QueryString["id"] != null)
            ImageID = Convert.ToInt32(context.Request.QueryString["id"]);
        else
            throw new ArgumentException("No parameter specified");
    
        SqlCommand cmd = new 
          SqlCommand($@"select FileName,MyImage FROM Fighters where id = @id");
        cmd.Parameters.Add("@ID", SqlDbType.Int).Value = ImageID;
        DataTable dt = General.MyRstP(cmd);
    
        context.Response.ContentType = MimeMapping.GetMimeMapping(dt.Rows[0]["FileName"].ToString());
        context.Response.BinaryWrite((byte[])dt.Rows[0]["MyImage"]);
    
    }
    

    And now the markup for the image control can look like this:

                    <asp:Image ID="Image2" runat="server" Width="180" Height="120"
                     ImageUrl='<%# @"~/MyImage2.ashx?id=" + Eval("ID") %>'   />
    

    So, the result is much the same, but a BIG whopper of a difference is the 2nd example will cache the image, and if you need/want/expect to have post-backs on that page, then the 2nd example is STRONG suggested if the images are anything more then a rather small type of thumbnail preview.

    With the first example, the images are not cached, and if you need post-backs, then the view state will actaully be sending the images BACK to the server when you post-back. This thus can be rather slow.

    I actually recommend with the first example that one disable view state for the image control.

    Note that with this 2nd example, you have to create that image handler page, but you do thus remove the on row data bound code. So, a trade off here.

    So, while your post SPECIFIC asked for not creating a handler?

    it is a good idea – and how important to use a handler will be based on many factors, such as how many images, how big they are, and does the resulting page require post-backs. You have to pay VERY close attention to this issue of post-backs, since if you don’t, such pages can run VERY slow with a poor internet connection.

    Login or Signup to reply.
  2. You need to use web method API that receives imageKey and write in response image file.
    if use Asp.Net Form ,I suggest check Global.asx abilities.
    If use Mvc , I suggest write a action that return FileResult

    Now use url of web method api in your ui
    code :

    <asp:Repeater ID="Repeater1" runat="server">
           <ItemTemplate>
              <asp:image src=<%#Eval("ImageUrl")%>>
           </ItemTemplate>
        </asp:Repeater>
    

    another way is use base64 format for display your image that I do not suggest because it makes your page heavy.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search