19

I am trying to create a website to upload/display images (using MVC4). I have written the below code to fetch the images which are locally stored on the server under a folder App_Data\Images. The path for the image is stored in the ImageFile property of the model.

The view renders the ID, Caption of the various images but the image is not loaded. The image file exists in the path stored against the ImageFile property. How can I fix this?

//Model

public class Photo
{
    public int ID { get; set; }

    public string ImageFile { get; set; } //This contains a path where the image is locally stored on the server
    public string Caption { get; set; }
byte[] Image { get; set; } 
}

//Controller

private PhotoDBContext db = new PhotoDBContext();

public ActionResult Index()
{
    return View(db.Photos.ToList());
}

//View

@model IEnumerable<MyPhotoLibrary.Models.Photo>

<table>
 @foreach (var item in Model) {
 <tr>
    <td>
        <img src="@Url.Content(item.ImageFile)" alt="" />
    </td>
    <td>
        @Html.DisplayFor(modelItem => item.Caption)
    </td>
 </tr>
 }
</table>

Also, if I save the image as a byte array (instead of physically storing the file and using the file path), how can I re-create the image and display it in the view . i.e. how do I re-create the image from the byte array while iterating over the model in the view?

EDIT

I have been able to resolve the display problem by doing the below (both are needed) - 1) Changed the path to a relative path 2) Moved the images to a separate folder other than App_Data. (found this)

Thanks.

5
  • Hi. Right click in your browser and find the rendered source. You will see the path that is being rendered. Please check this is correct. You may need to follow the advice of @Gabe below and make sure you have used the right path type. Commented May 30, 2013 at 15:30
  • @KingCronus - Hi. Yes, I did check the path by viewing the source of the page. Its like - D:\TestProjects\MyPhotoLibrary\MyPhotoLibrary\App_Data\Images\Jellyfish.jpg. The image exists there. Commented May 30, 2013 at 15:34
  • 1
    There might well be your problem. The browser isn't able to access that address. Change it to something relative to the application root. Commented May 30, 2013 at 15:43
  • Why is your image property a byte array rather than a pointer to a relative path for where the image is stored on disk? Commented May 30, 2013 at 15:49
  • @senfo - I am storing the path in the ImageFile property (file is saved locally on the server as well) and had created the byte array to store the image in the database as well. Commented May 30, 2013 at 16:14

2 Answers 2

36

Make sure you image is a relative path such as:

@Url.Content("~/Content/images/myimage.png")

MVC4

<img src="~/Content/images/myimage.png" />

You could convert the byte[] into a Base64 string on the fly.

string base64String = Convert.ToBase64String(imageBytes);

<img src="@String.Format("data:image/png;base64,{0}", base64string)" />
Sign up to request clarification or add additional context in comments.

2 Comments

While saving the path of the image I use this: photo.ImageFile = Path.Combine(Server.MapPath("~/App_Data/Images"), Path.GetFileName(image.FileName)); How do I change the ImageFile property to have a relative path?
Actually, in MVC 4 (more specifically Razor 2), you don't need Url.Content, you can do <img src="~/Content/images/myimage.png" />
3

It is possible to use a handler to do this, even in MVC4. Here's an example from one i made earlier:

public class ImageHandler : IHttpHandler
{
    byte[] bytes;

    public void ProcessRequest(HttpContext context)
    {
        int param;
        if (int.TryParse(context.Request.QueryString["id"], out param))
        {
            using (var db = new MusicLibContext())
            {
                if (param == -1)
                {
                    bytes = File.ReadAllBytes(HttpContext.Current.Server.MapPath("~/Images/add.png"));

                    context.Response.ContentType = "image/png";
                }
                else
                {
                    var data = (from x in db.Images
                                where x.ImageID == (short)param
                                select x).FirstOrDefault();

                    bytes = data.ImageData;

                    context.Response.ContentType = "image/" + data.ImageFileType;
                }

                context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
                context.Response.BinaryWrite(bytes);
                context.Response.Flush();
                context.Response.End();
            }
        }
        else
        {
            //image not found
        }
    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
}

In the view, i added the ID of the photo to the query string of the handler.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.