Question

I'm not really sure if I'm using the WebImage class correctly.

I have a controller that pulls a photo and some related information (comments, upload date, file name) from the database. I want to return a partial view that contains this information, and display the image along with the extra info.

So I created a new WebImage from the byte array, but how do I display it?

According to this article it should be pretty simple

  1. You need to work with Razor syntax and create a variable that will contain the image:
    @{ var myImage = WebImage("/Content/myImage.jpg") // Work with the image… }

  2. Then, in order to load the image in the page, you have to show the variable that contains the image inside an HTML <img/> tag:
    <img src="@myImage"/>

Except that doesn't work, it just outputs <img src="System.Web.Helpers.WebImage"> and calling .Write doesn't help.

Is there any way to do this or do I need to split up my action into two different actions, one to return the photo information and one to return the photo itself?

Was it helpful?

Solution

There isn't anyway to do it in a single razor view... you need to create a seperate action to render the image.

The img tag on the page is going to make a SEPERATE http call to the server based on the url provided in the img src.

OTHER TIPS

You can write it out on the fly!

You just don't use WebImage.Save() like you'd think, instead you use WebImage.GetBytes().

In this example, you've already saved an image as a byte array to the database. Simplified it a bit to only handle jpegs.

    /// <summary>
    /// Reference this in HTML as <img src="/Photo/WatermarkedImage/{ID}" />
    /// Simplistic example supporting only jpeg images.
    /// </summary>
    /// <param name="ID">Photo ID</param>
    public ActionResult WatermarkedImage(Guid ID)
    {
        // Attempt to fetch the photo record from the database using Entity Framework 4.2.
        var photo = db.Photos.Find(ID);

        if (photo != null) // Found the indicated photo record.
        {
            // Create WebImage from photo data.
            // Should have 'using System.Web.Helpers' but just to make it clear...
            var wi = new System.Web.Helpers.WebImage(photo.Data); 

            // Apply the watermark.
            wi.AddImageWatermark(Server.MapPath("~/Content/Images/Watermark.png"), 
                                 opacity: 75, 
                                 horizontalAlign: "Center", 
                                 verticalAlign: "Bottom");

            // Extract byte array.
            var image = wi.GetBytes("image/jpeg");

            // Return byte array as jpeg.
            return File(image, "image/jpeg");
        }
        else // Did not find a record with passed ID.
        {
            return null; // 'Missing image' icon will display on browser.
        }
    }

Try using Data URLs to display the image. This will avoid temporarily saving the image to disk and a second HTTP request to fetch the image. You'll just need to do one round trip to encode the image inline.

I don't believe the WebImage helper provides the ability to write to a stream. Because of that, you'll likely need to save the file to a temp location (or a cacheable location) and then read the bytes, and write the image back as a FileStreamResult specifying the content type and the data.

You can convert WebImage into Base64 encoded string and use in a Data URL on the page. Using an HTML canvas makes this pretty easy to accomplish.

Server side generate the Base64 string and create the data url

// C# Razor code
WebImage myWebImage;
// you need to now set the WebImage object in your code
string imagebase64string = Convert.ToBase64String(myWebImage.GetBytes());
string dataUrl = string.Format("data:image/jpeg;base64,{0}", imagebase64string);

Using Razor syntax inject the data url into the Javascript code which renders the image in the browser when the page loads:

// Javascript Code
var myCanvas = document.getElementById('my-image-canvas');
var imageCtx = myCanvas.getContext('2d');
var myImage = new Image;
myImage.onload = function () {
   imageCtx.drawImage(myImage, 0, 0);
}
myImage.src = '@dataUrl';

Below is link to a sample application that demonstrates this concept as well as shows how to easily render ASP.Net charts using a single Razor page using the same concept.

https://github.com/webextant/webimage

I used @Brady321's approach (thanks ;) ) but my code looks a little different (see below). The advantage of Brady's approach is that the file does not need to be saved to disk - just uploaded and displayed!

WebImage photo = null;
var dataUrl = "";

if (IsPost)
{
    photo = WebImage.GetImageFromRequest();
    if (photo != null)
    {
        string imagebase64string = Convert.ToBase64String(photo.GetBytes());
        dataUrl = string.Format("data:image/jpeg;base64,{0}", imagebase64string);
    }
}

The file upload and display part looks like this:

<div class="col-md-4">
    <h2>Display Image on the Fly</h2>
    <h1>Displaying an Image On the Fly</h1>

    <form action="" method="post" enctype="multipart/form-data">
        <fieldset>
            <legend> Upload Image </legend>
            <label for="Image">Image</label>
            <input type="file" name="Image" />
            <br />
            <input type="submit" value="Upload" />
        </fieldset>
    </form>
    <h1>Uploaded Image</h1>
    @if (dataUrl != "")
    {
    <div class="result">

        <img src="@dataUrl" alt="image" />

    </div>
    }
</div>

The key part being: <img src="@dataUrl" alt="image" />

As well as my earlier answer, based on Brady321's answer, I have a similar alternative approach that works for ASP.NET 4.7.2 projects that do not use Razor/.cshtml. This is in VB.NET but would work in C# too:

 Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
            . . .
            If IsPostBack Then
                ' A postback
                Dim dataURL As String
                Dim photo As System.Web.Helpers.WebImage
                photo = System.Web.Helpers.WebImage.GetImageFromRequest()
                If (photo IsNot Nothing) Then
                    Dim imagebase64string As String
                    imagebase64string = Convert.ToBase64String(photo.GetBytes())
                    dataURL = String.Format("data:image/jpeg;base64,{0}", imagebase64string)
                    UploadedImage.Src = dataURL
                End If


            . . .
   End Sub

THe .aspx HTML looks like this (the lack of src parameter causes a warning but works fine):

                                          <form action="" method="post" enctype="multipart/form-data">
                                            <fieldset>
                                                <legend> Upload Image </legend>
                                                <label for="Image">Image</label>
                                                <input type="file" name="Image"  />
                                                <br />
                                                <input type="submit" value="Upload" id="Submit" onsubmit="UploadFile2" runat="server" />
                                            </fieldset>
                                        </form>
                                      <h1>Uploaded Images</h1>

                                      <img  alt="image" id="UploadedImage" runat="server" />
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top