4

I have a view which contains a users id and an image column.

Here's what i've tried doing to retrieve the image but i keep getting a box with an red x instead of the actual image.

View

<td><img src="<%= Url.Action( "DisplayImage" , "User" , new { id = item.id} ) %>" alt="" /></td>

Controller

  public FileContentResult DisplayImage(string id)
    {
        byte[] image = repository.GetImage(id);
        return File(image, "image/jpg");
    }

i've also tried returning an ActionResult instead and that didn't work either.

Repository

    public Byte[] GetImage(string id)
    {

        var image = db.GetImage(id).First<GetImageResult>();

        if (image == null)
            return null;
        return image.UserImage;
    }

LinqTOSQL Class

    [Function(Name="dbo.GetImage")]
public ISingleResult<GetImageResult> GetImage([Parameter(DbType="VarChar(8)")] string id)
{
    IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), id);
    return ((ISingleResult<GetImageResult>)(result.ReturnValue));
}

public partial class GetImageResult
{
    private System.Byte[] _userImage;

    public GetImageResult()
    {
    }


    [Column(Storage="_userImage", DbType="Image")]
    public System.Byte[] UserImage
    {
        get
        {
            return this._userImage;
        }
        set
        {
            if ((this. _userImage!= value))
            {
                this. _userImage = value;
            }
        }
    }
}

I've been killing myself all day trying to get this to work, but it just isn't working. The return type on the stored procedure is an integer (atleast when i look at parameters in SQL Server Management Studio it says integer), but i can't redefine that now can i?

It's actually hitting the DisplayImage Action with the correct parameters within the UserController and returning File(imageByteArray, "image/jpg") but only a box with red x is being displayed. Any help would be greatly appreciated.

edit: I've tried debugging by adding a Reponse.BinaryWrite(imageByteArray) within the action result and hitting the url directly by goign to http://localhost/User/DisplayImage?id=10101010 and the image for that user is displayed in mspaint.

edit2: I also did a view source and my html for that image tag came out as following.

<td>
    <img src='/User.mvc/GetImage?id=U00915441' alt="" />
</td>

Thanks

DaveRandom
  • 87,921
  • 11
  • 154
  • 174
zSynopsis
  • 4,854
  • 21
  • 69
  • 106
  • I've had a problem like this where it would just try to find the image by path and not from the Route. Have you tried debugging to see if the application goes into the controller? – Yuriy Faktorovich Nov 18 '09 at 17:49
  • It does hit the controller action DisplayImage(string id) and it goes through it without a problem – zSynopsis Nov 18 '09 at 18:29
  • use fiddler too to see exactly what comes back down the wire – Simon_Weaver Nov 18 '09 at 19:09
  • It's showing an actual image in the imageview tab in fiddler. When i go to textview it's displaying a weird string which ends with ,ImageMan by Data Techniques, Inc.þ{±¾YÆÎÖ(1$Þ – zSynopsis Nov 18 '09 at 20:05
  • And when i view source in my web browser i'm getting – zSynopsis Nov 18 '09 at 20:07

1 Answers1

3

Look at this question I had from a while back - the solution was special ActionResult type for images

Edit: Here's my code. I'm actually creating an ImageResult class from an Image that I created with GDI+ like this :

 return new ImageResult()
 {
      ImageFormat = spriteInfo.ImageFormat,
      EncodedImageBytes = spriteInfo.GetImageStream()
 };

The image result class is. You'll notice if I provide an EncodedImageBytes parameter it will send that to the output stream. This looks like exactly what you want. On the other hand if you're just passing in an Image then it will just write that Image out to the output stream.

 public class ImageResult : ActionResult
    {
        public ImageResult() { }
        public int? Quality { get; set; }
        public Image Image { get; set; }
        public ImageFormat ImageFormat { get; set; }
        public byte[] EncodedImageBytes { get; set; }

        public override void ExecuteResult(ControllerContext context)
        {
            // verify properties 
            if (EncodedImageBytes == null)
            {
                if (Image == null)
                {
                    throw new ArgumentNullException("Image");
                }
            }
            if (ImageFormat == null)
            {
                throw new ArgumentNullException("ImageFormat");
            }
            // output 
            context.HttpContext.Response.Clear();

            if (ImageFormat.Equals(ImageFormat.Bmp)) context.HttpContext.Response.ContentType = "image/bmp";
            if (ImageFormat.Equals(ImageFormat.Gif)) context.HttpContext.Response.ContentType = "image/gif";
            if (ImageFormat.Equals(ImageFormat.Icon)) context.HttpContext.Response.ContentType = "image/vnd.microsoft.icon";
            if (ImageFormat.Equals(ImageFormat.Jpeg)) context.HttpContext.Response.ContentType = "image/jpeg";
            if (ImageFormat.Equals(ImageFormat.Png)) context.HttpContext.Response.ContentType = "image/png";
            if (ImageFormat.Equals(ImageFormat.Tiff)) context.HttpContext.Response.ContentType = "image/tiff";
            if (ImageFormat.Equals(ImageFormat.Wmf)) context.HttpContext.Response.ContentType = "image/wmf";

            // output stream
            Stream outputStream = context.HttpContext.Response.OutputStream;
            if (EncodedImageBytes != null)
            {
                outputStream.Write(EncodedImageBytes, 0, EncodedImageBytes.Length);
            }
            else
            {
                ImageUtil.SaveImageToStream(outputStream, Image, ImageFormat, Quality);
            }
        }

    }
Community
  • 1
  • 1
Simon_Weaver
  • 140,023
  • 84
  • 646
  • 689
  • reply back if this doesnt help and ill dig up the code im using. i am actually creating images dynamically and serving them up with no problem - so i'm doing it from a byte stream – Simon_Weaver Nov 18 '09 at 19:06
  • Okay i didnt have the ImageUtil.SaveImageToStream function so i commented that out and ran it and i'm still getting the same error. Here's what i did in my Controller var imageResult = new ImageResult(); imageResult.EncodedImageBytes= repository.GetImage(id); imageResult.ImageFormat = ImageFormat.Bmp; return imageResult. I used the same view as i posted earlier and i'm still getting a red x. In fiddler i do see the actual image in the imageview tab, but it's not displaying. – zSynopsis Nov 18 '09 at 20:25
  • try System.IO.File.WriteAllBytes("test.bmp", bytes) within the action method and then verify you can load that image directly into the browser. look in Fiddler and see whats coming back - including the header. they have an ImageView tab - see if you see anything there. can all browsers load BMP? im not sure about that one. i think so, but check that too. bmp seems a bad format to be using anyway – Simon_Weaver Nov 18 '09 at 22:06
  • Okay i did what you said. And it does write the image to a file, but it doesn't display if i try to open the image up with I.E. or Chrome. It does display if i open it up with paint or any other picture application. I also tried changing the image type to jpeg and encountered the same results. In the imageview tab of fiddler i can see the image. – zSynopsis Nov 19 '09 at 17:30
  • The header portion in fiddler displays: HTTP/1.1 200 OK Server: ASP.NET Development Server/9.0.0.0 Date: Thu, 19 Nov 2009 17:20:08 GMT X-AspNet-Version: 2.0.50727 X-AspNetMvc-Version: 1.0 Cache-Control: private Content-Type: image/bmp Content-Length: 1712 Connection: Close – zSynopsis Nov 19 '09 at 17:31
  • 1
    then your problem is not related to MVC. its that the image cant be loaded by the browser. you need to reencode the image as JPG or PNG. since it is already BMP, and only 1712 bytes I'm assuming its not a photo. i'd recommend PNG then. you should encode the image as JPEG into the database. now you said you DID change the image type to jpeg. what do you mean by that? you cant just change content-type if thats what you're trying. you need to get to a point where you can File.WriteAllBytes() and load it in IE before worrying about MVC related issues – Simon_Weaver Nov 19 '09 at 23:10