0

I'm new to MVC (coming from object oriented C# exe apps) and Stackoverflow. I've been struggling with trying to run code efficiently using MVC. I have Model data that returns from the database and along with that data is a field of bytes that are a jpeg image. At this stage I've made one call to the database...

Now what I'm stuck on is that once the populated model data is in the view to be rendered, I can't simply loop over it and render the image in each data row. The only thing that I've found to make it work is to call and Action method that returns a FileContentResult, but this requires a new call back to the database for each image anew.

For solutions I've tried three different approaches that have netted the following problems:

  1. I can't seem to pass the byte array back to the controller via an Action method to satisfy how MVC wants to receive the FileContentResult back in the view. The Action method only wants to accept simple types.
  2. I obviously don't want to ask the controller to go back to the database for the byte data that I already have in the View, especially when this will involve several round trips for each entry in my Model data.
  3. Using Data Uri works, but it's not supported by enough browsers yet.

Could someone tell me what the best way to handle issues like this? Do I need to work with problem 1, or 2, or is there a different approach that I'm missing?

Here is the code I tried to use originally in problem 1 to pass the byte array back to the controller so I can render the FileContentResult:

<img src=" @{Html.RenderAction("RenderMemberImage", "Home", new { @pic = x.ThumbnailData });}" />

[HttpGet]
    public FileContentResult RenderMemberImage(byte[] pic)
    {
        return new FileContentResult(pic, "mime/jpeg");
    }
tereško
  • 58,060
  • 25
  • 98
  • 150
JDev
  • 3
  • 3

2 Answers2

1

One possible solution is to convert the byte to a Base64 representation and keep that as a property of your child object

public class Child
{
  public string ImageURL { set;get;}
  //other properties & construct etc 
}
public class Master
{
  IEnumerable<Child> Children { set;get;}
}

in your GET Action

public ActionResult SomeGetACtion()
{
  var master=new Master();

  foreach(itm in someCollection)
  {
    var child=new Child();

    byte[] imageData = GetImageByte(); //get your byte data;
    string imageBase64 = Convert.ToBase64String(imageData);
    child.ImageURL = string.Format("data:image/gif;base64,{0}", imageBase64);
    master.Children.Add(byte);
  }
}

You may use it in the view like this

@foreach(child in Model.Children)
{
  <img src="child.ImageURL" alt="loding.." />

}
Shyju
  • 214,206
  • 104
  • 411
  • 497
  • Yes, that is roughly what I've done with problem 3 that I mentioned above. Data URI I imagine will be used more in the future, but right now IE is behind "the times". It sounds like what I need to do is just not store images in the database but serve them from a file/application server at standard http addresses. What do you guys think? Thank you for the feedback. – JDev Jul 07 '12 at 18:25
0

The problem is that you're trying to send a byte array from the browser to the server. Try something like this:

(I haven't compiled this but it should be close)

<img src=" @{Html.Action("RenderMemberImage", "Home", new { @picId = x.Id });}" />

[HttpGet]
public FileContentResult RenderMemberImage(Guid picId)
{
    var pic = new Models.Picture(picId);//or however you get your data out of the DB
    return new FileContentResult(pic.ThumbnailData , "mime/jpeg");
}

Basically for each image on the page the browser will make a request to the server to get the image.

Ken Henderson
  • 2,828
  • 1
  • 18
  • 16
  • Thank you but I don't think you read my whole post. I DON'T want to go back to the server with byte data. I already have the byte data ON the client. I want to make use of it on the client side. I'm trying to find a way where I don't have to go back to the database as well as the web server, but preferably, I don't want to go back to the server at all. Does that make sense? – JDev Jul 06 '12 at 06:17
  • Actually I did read your whole post, as far as I know other than the Data URI method the scenario you are trying to make work isn't supported by the browser(s). As you probably know typically the `src` attribute of the image tag will link back to a route on the server that returns the image in a HttpResponse. If you don't want to setup your application to do this you're going to be swimming upstream trying to get this to work on multiple browsers. – Ken Henderson Jul 06 '12 at 17:19
  • Thanks. Like I replied to Shyju above about data URI, it sounds like what I want to do isn't ready in the web world yet and what I need to do is not store images in the database but serve them from a file/application server at standard http addresses. What do you think? – JDev Jul 07 '12 at 18:29
  • I'm assuming you have a good reason for putting the images in the database (ie. easy to update via a different controller/action?) so there's no problem with that. If the images are static and only change when the web app is update then I would not store them in the database for reasons of efficiency (less of a hit for IIS to return an image from the file system vs. the web app/database). If you do want to store them in the database then you can use my suggestion above to do so (ie. the image is returned by the controller as a 'view' result). – Ken Henderson Jul 07 '12 at 23:25
  • Not really a deliberate reason other than I had to manipulate the byte data to adjust the sizes of the images, so was easy to stick in a field in the database... other than that, I have been open to suggestions about how to store and retrieve it. I'm not a seasoned web developer and it's even been a while since I wrote many desktop apps, so it's been a learning curve, as usual. Thanks guys. – JDev Jul 10 '12 at 01:45