asp.net Image

FJK

Erfahrenes Mitglied
Hallo,

ich versuche mich grade etwas in die Programmierung von Webanwendungen einzuarbeiten.
Also MySQL und Asp.Net.
Ich nutze Visual Studio mit einer Leeren asp.net Seite. Nun wollte ich auf ein Image, ein Paar Koordinaten aus einer DB lesen und sie auf den Image Anzeigen.
In einer Windows Form Version, hätte ich mir jetzt ein Internes Bitmap erschaffen darauf etwas rumgekritzelt und es an das Image auf der Webseite übergeben. Nur kann ich scheinbar kein Bitmap mehr an das Image übergeben, der will immer eine URL haben.
Das Bitmap zwischen zu speichern finde ich jetzt aber auch nicht grade sinnvoll, dann müsste ich ja für jede IP die bestimmte Daten auswählt ein neues Bild auf der Platte ablegen.

Und kennt jemand Tutorials für die Progammierung von asp.net Seiten. Ich nutze C# und das was ich so bei google finde, basiert eher auf zusammen geklickten Seiten.

danke
 

Alexander Schuc

crazy-weasel
Hoi..


wie in Nicos Link auch gemacht wird: Erstell einfach wie gewohnt den Bitmap, und auch das darauf zeichnen funktioniert wie in einer WinForms Anwendung.. der Unterschied ist einfach, dass du das Bild auf den Antwortstream schreiben musst.

Für diese Aufgabe würde sich ein ASP.net Handler (.ashx) anbieten, da du den ganzen WebForms Kram (das Event-System vorallem) nicht brauchst.

lg,..
 

FJK

Erfahrenes Mitglied
Hi,

ja das mit dem "handler" habe ich auch schon bei google zu den Thema gefunden,
aber wie schreibe ich so einen Handler?
Das finde ich nicht.

zum link,
ich denke mal das wichtige ist:
Code:
64 Response.Clear(); 
65 Response.ContentType="image/jpeg"; 
66 bitmap.Save(memStream, ImageFormat.Jpeg); 
67 memStream.WriteTo(Response.OutputStream);

nur was bedeuten die einzelnen Zeilen?
vorallem "ImageFormat.Jpeg" was ist das, sieht ja fast nach ein Dateiname aus, nur "Save" will kein string.
 

Alexander Schuc

crazy-weasel
ImageFormat.Jpeg gibt an, mit welchem Codec das Bild gespeichert werden soll, sprich: den Dateityp. Dies muss mit dem angegebenen ContentType zusammenpassen.
Einen Dateinamen brauchst hier nicht angeben, da das Bild ja eh direkt an den Browser geschickt wird.

Hier ein kleines Beispiel mit einem Handler:

C#:
<%@ WebHandler Language="C#" Class="ClockImageHandler" %>

using System;
using System.Web;
using System.Drawing;
using System.Drawing.Imaging;

public class ClockImageHandler : IHttpHandler
{
    public void ProcessRequest (HttpContext context)
    {
        using (Bitmap bmp = new Bitmap(320, 240))
        {
            using (Graphics gfx = Graphics.FromImage(bmp))
            {
                gfx.Clear(Color.White);
                
                Font font = new Font("Verdana", 14f);
                
                string text = DateTime.Now.ToLongTimeString();

                SizeF textSize = gfx.MeasureString(text, font, bmp.Width);

                PointF textLocation = new PointF();

                textLocation.X = (bmp.Height - textSize.Height) / 2f;
                textLocation.Y = (bmp.Width - textSize.Width) / 2f;

                gfx.DrawString(text, font, Brushes.Black, textLocation);

                font.Dispose();
            }

            context.Response.ContentType = "image/png";
            
            bmp.Save(context.Response.OutputStream, ImageFormat.Png);
        }
    }
 
    public bool IsReusable
    {
        get {
            return false;
        }
    }

}

Bei diesem Beispiel wird das Bild als PNG Datei gespeichert, daher auch ImageFormat.PNG und auch der ContentType ist anders..

Den Code einfach als blabla.ashx speichern, auf deinen ASP.net befähigten Webserver laden, und im Browser aufrufen.


lg..
 

FJK

Erfahrenes Mitglied
gut aber wie sage ich jetzt dem Steuerelement das es diesem Stream nutzen soll?

also das ganze sieht dann so bei mir aus:
Code:
        protected void Page_Load(object sender, EventArgs e)
        {
           Daten aus der DB laden
           Bitmap bmp erschaffen
           mit Graphics drauf zeichnen
                       
           context.Response.ContentType = "image/png";            
           bmp.Save(context.Response.OutputStream, ImageFormat.Png);
        }
 
Zuletzt bearbeitet:

Alexander Schuc

crazy-weasel
Du kannst den Handler so verwenden, als wäre es eine normale Bilddatei die am Server liegt. Brauchst also nur den Pfad zur Datei angeben.

C#:
<asp:Image id="Image1" runat="server"
           AlternateText="mein generiertes Bild.."
           ImageUrl="~/blabla.ashx"/>

bzw.

C#:
image1.ImageUrl="~/blabla.ashx";

Das ganze geht natürlich auch mit einem normalen IMG-Tag.. ;)

HTML:
<img src="blabla.ashx" />
 

FJK

Erfahrenes Mitglied
sorry,
mir sind einige Sachen noch nicht ganz klar.
Bin grade erst seid ein paar Stunden in der asp.net Welt unterwegs.
bitte korrigiert mich wenn ich was falsches sage.

In VS, lege ich ein neue Website an (Leere ASP.NET-Website)
hier bekomme ich
-Default.aspx
-Default.aspx.cs

in der "Default.aspx.cs" befindet sich eine Methode "protected void Page_Load(object sender, EventArgs e)" diese Setze ich mit der "Load" Methode von WindowsForms gleicht, bzw gehe davon aus das die Methode aufgerufen wird wenn die Seite neu geladen wird, also auch zb bei "F5".

Nun wollte ich in diese Methode die Daten Laden das, das Bild erschaffen und anzeigen Lassen. Das das Laden und Erschaffen Funktioniert weiß ich, denn wenn ich das Bild auf der Festplatte Speichere stimmt es. Nur das Anzeigen funktioniert noch nicht.

Dafür benötige ich jetzt ein Handler der mir das erschaffene Bild vom Server zum User leitet. Das macht der Handler.
Dafür benötige ich eine neue Seite .ashx. wo ich diese Datei mit der Endung finde weiß ich nicht, denn unter "Projekt->Neues Element Hinzufügen" gibt es keine Datei mit ".ashx" als Endung.

In diese Datei müsste dann der Code
Code:
<%@ WebHandler Language="C#" Class="ClockImageHandler" %>
 
using System;
using System.Web;
using System.Drawing;
using System.Drawing.Imaging;
 
public class ClockImageHandler : IHttpHandler
{
    public void ProcessRequest (HttpContext context, Bitmap bmp)
    {
        context.Response.ContentType = "image/png";            
        bmp.Save(context.Response.OutputStream, ImageFormat.Png);
    }
 
    public bool IsReusable
    {
        get 
       {
            return false;
        }
    }
 
}

muss ich das in einer extra Datei machen, oder kann ich das auch in der "protected void Page_Load(object sender, EventArgs e)" Methode machen?

in der "protected void Page_Load(object sender, EventArgs e)" Methode müsste dann der Code:
Code:
        protected void Page_Load(object sender, EventArgs e)
        {
          Daten aus DB laden
          Bitmap Bild...
          Bild mit Graphics bearbeiten.
          aufruf von  ProcessRequest (HttpContext context, Bitmap bmp)
          Image.ImageUrl = blabla.ashx;
        }

wie sieht den der genaue Aufruf der Methode ProcessRequest (HttpContext context, Bitmap bmp) aus?
Was ist ein HttpContext?
Und wo müsste sich diese Methode befinden?

ist das so richtig?

gruß und danke
 
Zuletzt bearbeitet:

Alexander Schuc

crazy-weasel
Hoi..

Also was du bei ASP.net nicht vergessen darfst: Es ist eine Web Anwendung! Wie bei PHP etc. hast du da HTTP Anfragen im Hintergrund!

Die ASP.net WebForms setzen da einfach ein EventModel das an WinForms erinnert drauf, aber dennoch gibt es die von HTTP gegebenen Einschränkungen.

Dein von dir beschriebener Ablauf kann nicht funktionieren, da der Aufruf von "Default.aspx" und von "blabla.aspx" 2 getrennte HTTP Aufrufe sind.

Das erstellen des Bildes muss komplett im HttpHandler geschehen.

Sehen wir uns kurz mal an, wie der Ablauf ist, wenn ein User auf deine Default.aspx gelangt. (Wir nehmen an, dass das Beispiel korrekt funktioniert.)

* User tippe http://bla.com/Default.aspx im Browser ein
* Am Server lädt ASP.net deine Seite, und feuert schlussendlich irgendwann das Page-Load-Event
* Dein Code setzt die Url eines Image-Controls auf deinen HttpHandler (blabla.ashx)
* Der erste Aufruf ist fertig, der Browser bekommt das resultierende HTML Ergebnis
* Im HTML Code findet er ein Img-Tag, mit einer gültigen Adresse.
* Der Browser ruft die zuvor gefundene Adresse auf, da er das Bild anzeigen möchte.
* Am Server wird der Aufruf wieder an ASP.net geleitet, diesmal an den Handler. ProcessRequest wird aufgerufen.
* Dein Handler erstellt das Bild, und schreibt es auf den Antwortstream.
* Der Browser liest das Bild, und zeigt es an.

Auf grund dieses Ablaufs kannst du das Bild nicht im ersten Aufruf erstellen. Du kannst es nämlich nicht direkt mitsenden (gibt ne Ausnahme, aber die ist irrelevant), und dein HttpHandler weiss gar nichts von Default.aspx und könnte auch nicht auf ein dort erstelltes Bild zugreifen.
Zu dem Zeitpunkt wo blabla.ashx aufgerufen wird, ist die Verarbeitung von Default.aspx mit hoher Wahrscheinlichkeit schon abgeschlossen.

Du brauchst also für den Handler eine eigene Datei, da es einen ganz eigenen Aufruf darstellt.

Es gibt übrigens noch eine 2. Möglichkeit einen Handler zu implementieren. Dazu erstellst dir eine Code-Datei in deinem App_Code Verzeichnis (blabla.cs), schreibst dort deine Handler-Klasse hinein, und registrierst anschließend den Handler in der web.config.

Code:
<configuration>
  <system.web>
    <httpHandlers>
	  <add verb="*" path="blabla.ashx" type="ClockImageHandler" />
	</httpHandlers>
  </system.web>
</configuration>

Ansonsten füge einfach irgend eine Datei deinem Projekt hinzu, und benenne diese um. Das funktioniert problemlos. :)

Ists dir jetzt ein bisschen klarer geworden?

lg
 

FJK

Erfahrenes Mitglied
vom ablauf her ja, danke,
aber von der Programmierung her noch nicht ganz. Mir ist immer noch nicht klar wo ich jetzt was hinsetzen muss. Bzw wie ich den Handler aufrufen soll.
In der ashx kennt er auch die mysql dll nicht.
Kannst du mir bitte noch ein leichten tritt in die richtige Richtung geben?
wo wird die Seite den jetzt erstellt, beim User oder auf dem Server?