views:

404

answers:

1

Hi all,

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

+3  A: 

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);
            }
        }

    }
Simon_Weaver
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
Thanks. Can you please post some code?
zSysop
hope this helps
Simon_Weaver
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 Controllervar 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.
zSysop
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
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.
zSysop
The header portion in fiddler displays: HTTP/1.1 200 OKServer: ASP.NET Development Server/9.0.0.0Date: Thu, 19 Nov 2009 17:20:08 GMTX-AspNet-Version: 2.0.50727X-AspNetMvc-Version: 1.0Cache-Control: privateContent-Type: image/bmpContent-Length: 1712Connection: Close
zSysop
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
Thanks i did that and it worked!
zSysop
ok great! BMPs are huge files anyway
Simon_Weaver