3

When I try to display a byte[] array image inside a Details page template using:

public FileContentResult RenderPhoto(byte[] photo)
{
    // var array = (byte[])Session["photo"];
    // return File(array, "image/jpeg");

    return File(photo, "image/jpeg");
}

<img src="@Url.Action("RenderPhoto", Model.Photo)"/>

photo is null.

If I store student.Photo in Session:

//
// GET: /Student/Details/5

public ViewResult Details(int id)
{
    Student student = db.Students.Find(id);

    Session["photo"] = student.Photo;

    return View(student);
}

and try to display the image retrieving the value from Session (commented lines above) it works.

Why I'm getting a null value in the first case?

After passing student to the View in ViewResult Details(int id), Model.Photo doesn't hold that value anymore?

Leniel Maccaferri
  • 100,159
  • 46
  • 371
  • 480

2 Answers2

11

Why I'm getting a null value in the first case?

You cannot pass a byte array to the server in an <img> tag. The <img> tag simply sends a GET request to the designated resource. The correct way to do this is to use an id:

<img src="@Url.Action("RenderPhoto", new { photoId = Model.PhotoId })" />

and then:

public ActionResult RenderPhoto(int photoId)
{
    byte[] photo = FetchPhotoFromDb(photoId);
    return File(photo, "image/jpeg");
}
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • if I do this I'll query the database just to get the photo. I already have the photo when I load student in the Details ViewResult method. – Leniel Maccaferri Apr 21 '11 at 06:00
  • I'm starting to think of implementing this in a different way. I'll have a model to represent a Photo (a table in the DB). I'll then create a relationship between Student and Photo. This way this scenario will make more sense. Student will have a PhotoId field that I'll use to query the DB. – Leniel Maccaferri Apr 21 '11 at 06:10
1

First of all

Url.Action("RenderPhoto", Model.Photo)

Will not work, Model.Photo (presumably your byte array) will be treated as an Object to infer route values of. It'll generate a route with the public properties of an Array object, probably along the lines of

?IsFixedSize=true&IsReadOnly=false&Length=255

That is going to be a pretty unhelpful url. Once the page loads in the browser, the browser will request that image, calling your RenderPhoto method, but there is no parameter called photo, so binding would fail, and even if there was a parameter called photo there (AFAIK) no logic in the DefaultModelBinder for creating a byte array from a string, hence photo is null.

What you need to do is pass an anonymous object with an Id property into Url.Action

Url.Action("RenderPhoto", new { Id = Model.PhotoId })

That will be converted to a querystring possibly along the lines of the following (but it depends on your routes)

/xxx/RenderPhoto/25

And you then need to retreive the data for the photo in your RenderPhoto method

Martin

Martin Booth
  • 8,485
  • 31
  • 31
  • that's it man. I was getting something like that string you posted above with the public properties of the array object. As I said I'll implement it in a different way so that I do not have to go to the database one more time just to get the photo. Student will have only the PhotoId and not the Photo itself. – Leniel Maccaferri Apr 21 '11 at 06:19