none
dynamische grafik mit ajax RRS feed

  • Frage

  • Hallo,
    ich möchte in einer website mit asp.net eine dynamische grafik in einem update panel erstellen
    dazu habe ich ein usercontrol erstellt, in dem die grafik über eine schnittstelle (eigenschaft bitmap) in einer session-variable gespeichert wird
    In der funktion render wird ein img-tag erzeugt und der link für die grafik erzeugt
    in der onInit funktion wird die grafik aus der session variable gelesen und schließlich an den client gesendet

    Das funktioniert solange, wie es kein update panel als Container in der aufrufenden seite für das user-control gibt.
    erfolgt ein asysnchroner postback, dann wird die oninit-methode nicht mehr durchlaufen

    Wie erzeuge ich also ein erneutes laden sprich ( request -response ) für einen asysnchronen postback?

     

    Imports System.ComponentModel, System.Drawing, System.Drawing.Drawing2D, System.Drawing.ImagingPartial 
    Public Class canvas Inherits System.Web.UI.UserControl
    Public myBMP As Bitmap
    
    Public Property bitmap() As Bitmap
    Get
    Return DirectCast(Session(String.Concat(Me.UniqueID, "_Bitmap")), Bitmap)
    End Get
    Set(ByVal value As Bitmap)
    Session([String].Concat(Me.UniqueID, "_Bitmap")) = value
    End Set
    End Property
     
    Protected Overrides Sub Render(ByVal output As System.Web.UI.HtmlTextWriter)
    Dim myurl As String = Request.Url.ToString
    myurl = String.Concat(myurl, "?", Me.UniqueID, "=1")
    output.Write("<img id=""{0}"" src=""{1}"" />", Me.UniqueID, myurl)
    End Sub
     
    Protected Overrides Sub OnInit(ByVal e As System.EventArgs)
    If Request.Params(UniqueID) IsNot Nothing Then
    If Session([String].Concat(Me.UniqueID, "_Bitmap")) IsNot Nothing Then
        myBMP = DirectCast(Session(String.Concat(Me.UniqueID, "_Bitmap")), Bitmap)
    Else  
       myBMP = New Bitmap(10, 10)
    End If
    Response.Clear()
    Response.ContentType = "image/GIF"
    myBMP.Save(Response.OutputStream, ImageFormat.Gif)
    Response.[End]()
    End If
    End Sub
    End Class
    Dienstag, 9. Februar 2010 16:22

Antworten

  • Hi,
    ich möchte in einer website mit asp.net eine dynamische grafik in einem update panel erstellen
    dazu habe ich ein usercontrol erstellt, in dem die grafik über eine schnittstelle (eigenschaft bitmap) in einer session-variable gespeichert wird
    In der funktion render wird ein img-tag erzeugt und der link für die grafik erzeugt
    in der onInit funktion wird die grafik aus der session variable gelesen und schließlich an den client gesendet
    deine Vorgehensweise ist denkbar ungeeignet um eine Grafik auszuliefern.

    Erstell dir einen Handler, der die Grafik erzeugt und referenziere diesen dann im src Attribut des img Tags. Wenn Du einen Zufallsparameter (bspw. eine Zufallszahl) anhängst, wird die auch immer neu vom Server geladen.

    <%@ WebHandler Language="VB" Class="ImageHandler" %>
    
    Imports System
    Imports System.Web
    Imports System.Drawing
    Imports System.Drawing.Imaging 
    Imports System.Drawing.Drawing2D
    Imports System.IO
    
    Public Class ImageHandler : Implements IHttpHandler
        
    Public Sub ProcessRequest(ByVal ctx As HttpContext) Implements IHttpHandler.ProcessRequest 
    
    Dim Output  As Bitmap   = ... 
    Dim Graphic As Graphics = Graphics.FromImage( Output ) 
        ...
    
        ctx.Response.Clear 
        ctx.Response.ContentType = "image/gif" 
        ctx.Response.AddHeader("Content-Disposition","inline;filename=test.gif") 
    
        Output.Save( ctx.Response.outputstream, ImageFormat.GIF ) 
    
        Graphic.dispose() 
        Output.dispose() 
    
        ctx.Response.End 
    
    End Sub 
     
    Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
        Get
            Return False
        End Get
    End Property
    
    End Class
    
    Wenn die obige Datei bspw. als Handler/ImageHandler.ashx abgespeichert ist, kannst Du die im img Tag mit src="/Handler/ImageHandler.ashx?12345678" referenzieren. 12345678 ist der Zufallsparameter.

    BTW: Ich hab ja schon viel gesehen aber eine Bitmap als Sessionvariable? Aua! (Es sei denn, dein Server hat 20 Terabyte RAM :)


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community
    Dienstag, 9. Februar 2010 17:37
    Moderator

Alle Antworten

  • Hi,
    ich möchte in einer website mit asp.net eine dynamische grafik in einem update panel erstellen
    dazu habe ich ein usercontrol erstellt, in dem die grafik über eine schnittstelle (eigenschaft bitmap) in einer session-variable gespeichert wird
    In der funktion render wird ein img-tag erzeugt und der link für die grafik erzeugt
    in der onInit funktion wird die grafik aus der session variable gelesen und schließlich an den client gesendet
    deine Vorgehensweise ist denkbar ungeeignet um eine Grafik auszuliefern.

    Erstell dir einen Handler, der die Grafik erzeugt und referenziere diesen dann im src Attribut des img Tags. Wenn Du einen Zufallsparameter (bspw. eine Zufallszahl) anhängst, wird die auch immer neu vom Server geladen.

    <%@ WebHandler Language="VB" Class="ImageHandler" %>
    
    Imports System
    Imports System.Web
    Imports System.Drawing
    Imports System.Drawing.Imaging 
    Imports System.Drawing.Drawing2D
    Imports System.IO
    
    Public Class ImageHandler : Implements IHttpHandler
        
    Public Sub ProcessRequest(ByVal ctx As HttpContext) Implements IHttpHandler.ProcessRequest 
    
    Dim Output  As Bitmap   = ... 
    Dim Graphic As Graphics = Graphics.FromImage( Output ) 
        ...
    
        ctx.Response.Clear 
        ctx.Response.ContentType = "image/gif" 
        ctx.Response.AddHeader("Content-Disposition","inline;filename=test.gif") 
    
        Output.Save( ctx.Response.outputstream, ImageFormat.GIF ) 
    
        Graphic.dispose() 
        Output.dispose() 
    
        ctx.Response.End 
    
    End Sub 
     
    Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
        Get
            Return False
        End Get
    End Property
    
    End Class
    
    Wenn die obige Datei bspw. als Handler/ImageHandler.ashx abgespeichert ist, kannst Du die im img Tag mit src="/Handler/ImageHandler.ashx?12345678" referenzieren. 12345678 ist der Zufallsparameter.

    BTW: Ich hab ja schon viel gesehen aber eine Bitmap als Sessionvariable? Aua! (Es sei denn, dein Server hat 20 Terabyte RAM :)


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community
    Dienstag, 9. Februar 2010 17:37
    Moderator
  • Hallo Stefan,
    danke für den Tip, funktioniert wunderbar - auch mit dem UpdatePanel. Es flackert zwar noch leicht beim Aufbau, aber da muss ich wohl noch ein wenig testen.

    Kann man dieser Klasse auch Daten übergeben, zb. eine DataTable? Ich möchte die Grafik für Daten aus einer Datenbankabfrage erstellen? Diese Abfrage erfolgt in der Startseite.

    Ich hatte das Ganze vorher mit der Speicherung des Outputs in einer festen Datei auf dem Server, welche dann als src für das image-element diente.
    Hat im MIE auch gut funktioniert, allerdings nicht im Mozilla Firefox. Dort wurde das UpdatePanel mit dem Image nicht erneuert. Wenn man sich die Grafik einzeln anzeigen lassen hat, war die richtige Datei heruntergeladen - aber sie erschien nicht im image (erst nach einem erneuten Laden der gesamten Seite).
    Außerdem schien mir die gespeicherte Datei auf dem Server auch nicht so ganz ok zu sein.

    Die Sache mit der Sessionvariable habe ich in der Fachliteratur gefunden. Von der Größe her hat es für meine Zwecke ausgereicht. Allerdings hat es eben nicht mit dem UpdatePanel funktioniert, weil die onInit Methode für den asynchronen Postback nicht durchlaufen wird.

    Deshalb würde mich trotzdem interessieren, wie man für ein Element mit einem asynchronen Postback ein request- response erzeugt. Ich denke, daß das über (wahrscheinlich clientseitigen) javascript-Aufrufe erfolgen müßte. Kennst du Dich aus?

    Danke und Gruß
    Claudia
    Donnerstag, 11. Februar 2010 16:30
  • Hallo Claudia.
    Kann man dieser Klasse auch Daten übergeben, zb. eine DataTable? Ich möchte die Grafik für Daten aus einer Datenbankabfrage erstellen? Diese Abfrage erfolgt in der Startseite.
    Dann solltest Du die Abfrage im Handler machen. Übergeben kannst Du die Daten nicht ohne weiteres, außer ggfs. im QueryString (oder Sessio, was aber definitiv nicht zu empfehlen ist)
    Die Sache mit der Sessionvariable habe ich in der Fachliteratur gefunden.
    Wenn das wirklich so da drin stand, wie es von dir angewendet wurde, kanns keine Fach literatur gewesen sein.
    Deshalb würde mich trotzdem interessieren, wie man für ein Element mit einem asynchronen Postback ein request- response erzeugt. Ich denke, daß das über (wahrscheinlich clientseitigen) javascript-Aufrufe erfolgen müßte. Kennst du Dich aus?
    Ich weiß ehrlich gesagt nicht wirklich, was Du meinst. Beschreib etwas detaillierter, was genau Du machen willst, am besten mit einem Beispiel.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community
    Samstag, 13. Februar 2010 15:12
    Moderator
  • Dann solltest Du die Abfrage im Handler machen. Übergeben kannst Du die Daten nicht ohne weiteres, außer ggfs. im QueryString (oder Sessio, was aber definitiv nicht zu empfehlen ist)
    Das habe ich mir schon fast gedacht, dass das mit der Übergabe nicht so einfach geht.  Kann ich denn wenigstens in dieser Klasse auf Instanzen aus der Web-Seite zugreifen, da ich für die Abfrage natürlich ein paar Eingaben des Nutzers (z.B. abzufragende Zeiträume, ...) benötige.
    Das kann ich aber auch selber testen.

    Deshalb würde mich trotzdem interessieren, wie man für ein Element mit einem asynchronen Postback ein request- response erzeugt. Ich denke, daß das über (wahrscheinlich clientseitigen) javascript-Aufrufe erfolgen müßte. Kennst du Dich aus?

    Ich weiß ehrlich gesagt nicht wirklich, was Du meinst. Beschreib etwas detaillierter, was genau Du machen willst, am besten mit einem Beispiel.
    Ich meine, wenn ich ein UpdatePanel mit einem Element habe (Label, Textbox,img ...) habe und nicht das udp.update nutzen kann oder will, sondern diese Funktion clientseitig per script initiieren möchte. Dann muss ich wahrscheinlich den Scriptmanager benutzen.
    Ich kann Dir dazu keinen Code geben, da ich eben nicht weiß, wie ich es implementieren soll. Aber ich denke irgenwo in diesem Bereich muß der asynchrone request für das update panel implementiert werden.

    <body>
        <form id="form1" runat="server">
        <div >
            <asp:ScriptManager ID="ScriptManager1" OnAsyncPostBackError="ScriptManager1_AsyncPostBackError"
                runat="server" />
            <script type="text/javascript">
          function pageLoad() { 
          }
        var prm = Sys.WebForms.PageRequestManager.getInstance();
    //    var tm=Sys.WebForms.InitializeRequestEventArg
        
         prm.add_beginRequest(BeginRequestHandler);
         function BeginRequestHandler(sender, args)
         {                
             var elem = args.get_postBackElement();
    
    // } prm.add_initializeRequest(InitializeRequest); function InitializeRequest(sender, args) { ClearErrorState(); if (prm.get_isInAsyncPostBack()) { // args.set_cancel(true); } } function AbortPostBack() { if (prm.get_isInAsyncPostBack()) { prm.abortPostBack(); } } prm.add_endRequest(EndRequestHandler); ...

    Gruß
    Claudia
    Montag, 15. Februar 2010 15:45
  • Hallo Claudia,
    Das habe ich mir schon fast gedacht, dass das mit der Übergabe nicht so einfach geht.  Kann ich denn wenigstens in dieser Klasse auf Instanzen aus der Web-Seite zugreifen, da ich für die Abfrage natürlich ein paar Eingaben des Nutzers (z.B. abzufragende Zeiträume, ...) benötige.
    Diese Werte musst/solltest Du mit übergeben. Man kann das zwar alles "irgendwie" auch über Sessionübergabe, ... lösen aber sinnvoll und zielführend ist das nicht.

    Zur Not schreib die Werte in eine Datenbank/Datei/... und übergib dann nur einen eindeutigen Kennzeichner, anhand dessen der handler die benötigten Daten wieder auslesen kann.
    Ich meine, wenn ich ein UpdatePanel mit einem Element habe (Label, Textbox,img ...) habe und nicht das udp.update nutzen kann oder will, sondern diese Funktion clientseitig per script initiieren möchte. Dann muss ich wahrscheinlich den Scriptmanager benutzen.
    Dazu siehe bspw.: http://codeclimber.net.nz/archive/2007/06/26/how-to-refresh-an-updatepanel-from-javascript.aspx

    Wobei ich dazu rate, das UpdatePanel in der Form nicht zu verwenden. Arbeite lieber mit jQuery, da wirst Du auf Dauer mehr Freude haben :)

    http://www.google.de/#q=jquery+updatepanel
    http://www.aspnetzone.de/blogs/robertobez/archive/2009/11/02/asp-net-Ajax-UpdatePanel-Callback-jQuery-Webservice.aspx
    ...


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community
    Dienstag, 16. Februar 2010 14:52
    Moderator