Вопрос

I'm a newb when it comes to creating an ASP.NET custom user control that will render and return .png charts to an ASP.NET web application.

I've created a simple sandbox project that creates an ellipse on a bitmap, renders it to a MemoryStream, and now I want to stream the output connected via an HTTP handler so as to render an asp:image in my markup page.

My problem is that I don't know how to connect the MemoryStream created in my usercontrol to the GetImage method of the http handler. I know that the GetMethod of the HTTP Handler creating a memory stream within the method isn't correct, but I don't know how to access the memorystream of the codebehind.

My prototype test project code is:

namespace ChartControl
{
    public partial class ChartCtl : System.Web.UI.UserControl
    {

        private int imageHeight = 150;
        private int imageWidth = 400;

        protected void Page_Load(object sender, EventArgs e)
        {
            renderChart();
        }

        protected MemoryStream renderChart()
        {
            Image imgChart = new Bitmap(imageWidth, imageHeight);
            Graphics g = Graphics.FromImage(imgChart);
            Rectangle r = new Rectangle(0, 0, imageWidth, imageHeight);
            g.DrawEllipse(Pens.Orange, g.VisibleClipBounds);
            MemoryStream ms = new MemoryStream();
            imgChart.Save(ms, ImageFormat.Png);
            return ms;
        }
     }
}

My HTTP Handler is:

namespace WIChart.UserControls
{
    public class ImageHandler : IHttpHandler
    {
        public void ProcessRequest(HttpContext context)
        {
            context.Response.Clear();

            if (!String.IsNullOrEmpty(context.Request.QueryString["id"]))
            {
                int id = Int32.Parse(context.Request.QueryString["id"]);

                // Now we have the id, just pass it to GetImage to build the image
                Image image = GetImage(id);
                context.Response.ContentType = "image/png";
                image.Save(context.Response.OutputStream, ImageFormat.Png);
            }
            else
            {
                context.Response.ContentType = "text/html";
                context.Response.Write("<p>Valid id is required.</p>");
            }
        }
        #region IHttpHandler Members

        public bool IsReusable
        {
            get { return false; }
        }

        private Image GetImage(int id)
        {
            MemoryStream stream = new MemoryStream();
            return Image.FromStream(stream);
        }
        #endregion
    }

}

My .ascx page is:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="ChartCtl.ascx.cs" Inherits="ChartControl.ChartCtl" %>
<%@ Register Assembly="System.Web.DataVisualization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" Namespace="System.Web.UI.DataVisualization.Charting" TagPrefix="asp" %>


<div class="content-wrapper">
    <div class="float-left">
        <p class="site-title">
            <asp:Image id="imgChart" ImageUrl="~/ImageHandler.ashx?id=1" runat="server" />
        </p>
    </div>
</div>

Thank you for any help that you can provide!

Это было полезно?

Решение

I couldn't understand what exactly you need here. But You can load image from user control using below code.

using System.Web;
using System.Web.UI;
using System.IO;

namespace WebApplication1
{
    public class ImageHandler : Page, IHttpHandler
    {
        public new void ProcessRequest(HttpContext context)
        {
            context.Response.Clear();
            ChartCtl chartCtl = (ChartCtl)LoadControl(ResolveClientUrl("ChartCtl.ascx"));
            MemoryStream ms = new MemoryStream();
            ms = chartCtl.renderChart(ms);

            context.Response.Clear();
            context.Response.ContentType = "image/jpeg";
            context.Response.BinaryWrite(ReadFully(ms));
            context.Response.End();
        }

        public static byte[] ReadFully(Stream input)
        {
            byte[] buffer = new byte[16 * 1024];
            using (MemoryStream ms = new MemoryStream())
            {
                int read;
                while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
                {
                    ms.Write(buffer, 0, read);
                }
                return ms.ToArray();
            }
        }

        #region IHttpHandler Members

        public new bool IsReusable
        {
            get { return false; }
        }

        #endregion
    }

}

HTML-

<asp:Image ID="imgChart" ImageUrl="~/ImageHandler.ashx" runat="server" />

ChartCtrl -

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;

namespace WebApplication1
{
    public partial class ChartCtl : System.Web.UI.UserControl
    {
        private int imageHeight = 150;
        private int imageWidth = 400;

        public MemoryStream renderChart(MemoryStream ms)
        {
            Image imgChart = new Bitmap(imageWidth, imageHeight);
            Graphics g = Graphics.FromImage(imgChart);
            Rectangle r = new Rectangle(0, 0, imageWidth, imageHeight);
            g.DrawEllipse(Pens.SteelBlue, g.VisibleClipBounds);
            imgChart.Save(ms, ImageFormat.Jpeg);                    // save the image to the memorystream to be processed via the Image/HttpHandler
            imgChart.Save(Context.Response.OutputStream, ImageFormat.Jpeg);    // save to drive just to verify that image is being properly created.
            return ms;
        }
    }
}

Web.Config [IIS 7] -

<system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
    <handlers>
      <add name="ImageHandler" verb="*"
       path="ImageHandler.ashx"
       type="WebApplication1.ImageHandler, WebApplication1"
       resourceType="Unspecified" />
    </handlers>
  </system.webServer>

Mem Stream to byte array conversion is from Creating a byte array from a stream

Check this link also http://www.codeproject.com/Articles/34084/Generic-Image-Handler-Using-IHttpHandler

P.S - I don't know why your code is being executed only with constructor. Without constructor I'm able to execute the code. When you are loading a web control from Handler, normal page events wouldn't get executed. We need call methods manually.

I think You need to host your website in IIS to get HTTpHandler called, I am not sure about this part.

Другие советы

You are coming at this a bit backwards with using your imagehandler as a page -- try to think of the page as static HTML where you are referencing an image and the answer is pretty straightforward. What you need to do is add an image tag referencing your graphic-generating handler -- ie <img src="~/MyHandler.ashx" />.

The challenge then becomes how to marshal data into the handler. There are loads of ways to handle this, the basic ones being query string variables if the data is simple or a query string with enough data so the handler can go back and load it's own data.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top