xcelm
xcelm

Reputation: 571

Uploading and displaying image in ASP.NET MVC

I have hard time uploading picture and then displaying it in my view. I went through a lot of posts here and for some reason nothing really works for me.

Picture gets uploaded (in my case saved in ~/Content/Images, but is not displayed in the view. Whole project is published on Azure.

Please abstract from things like verifying if the uploaded file is really a picture or handling the size of the picture.

My domain model is:

public class Product
{
    ...
    public string ProductImageUrl { get; set; }
    ...
}

Controller - post method:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(/*[Bind(Include = "ProductId,ProductName,ProductDescription,ProductPrice, CategoryId, Quantity, picture")]*/ Product product, HttpPostedFileBase picture)
{
   if (ModelState.IsValid)
   {
        db.Products.Add(product);

        if (picture != null)
        {
             var originalFileName = Path.GetFileName(picture.FileName);
             string fileId = Guid.NewGuid().ToString().Replace("-", "");
             var path = Path.Combine(Server.MapPath("~/Content/Images/"), fileId + ".jpg");

             picture.SaveAs(path);

             product.ProductImageUrl = path;
             product.ProductImageName = fileId;

             db.SaveChanges();
        }

        db.SaveChanges();

        return RedirectToAction("Index");
     }

     return View(product);
} 

My view is:

       @foreach (var item in Model)
        {
            <tr>
                <td>
                    <img src="@item.ProductImageUrl" />
                </td>
...

Upvotes: 4

Views: 5166

Answers (4)

TanvirArjel
TanvirArjel

Reputation: 32159

Problem is that your are storing absolute path in the ProductImageUrl field and that's why its not working in your hosting environment. More importantly you don't need both ProductImageUrl and ProductImageName to handle images. Use only ProductImageName.

Do as follows:

Your Product model should as follows:

public class Product
{
    ...
    public string ProductImageName { get; set; }
    ...
}

Then in the Controller method:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Product product, HttpPostedFileBase productImage)
{
   if (ModelState.IsValid)
   {
      if (productImage != null && productImage.ContentLength > 0)
      {
          var fileName = Guid.NewGuid().ToString().Replace("-", "") + "_" + Path.GetFileName(productImage.FileName);
          var path = Path.Combine(Server.MapPath("~/Content/Images/Product/"), fileName);

          productImage.SaveAs(path);
          product.ProductImageName = fileName;
      }

      db.Products.Add(product);
      await db.SaveChangesAsync();
      return RedirectToAction("Index");
   }

   return View(product);
} 

Then in the View as follows:

@foreach (var item in Model)
{
   <tr>
       <td>
           <img src="@Url.Content("~/Content/Images/Product/"[email protected])" />
       </td>
   <tr>
}

Hope it will work for you! Thank you.

Upvotes: 4

Crowcoder
Crowcoder

Reputation: 11514

I would add a <base> tag to your view so that all links are relative to your site. Then you don't need to build a path to the image at all.

For intance, if you site is at https://bestsiteever.com your tag would look like this:

<base href="https://bestsiteever.com" >

and your path would be:

$"/Content/Images/{fieldId}.jpg"

Upvotes: 1

Ihusaan Ahmed
Ihusaan Ahmed

Reputation: 543

Correct me if i'm wrong but the string stored in item.ProductImageUrl is a path like c:\\.. right?

Server.MapPath gives relative hard drive location on the server. If you put that location in src then you are asking the browser to find that file in your LOCAL hard drive.

Try item.ProductImageUrl = "<url to your site>/Content/Images/" + fileId + ".jpg";.

Upvotes: 0

Mirko Acimovic
Mirko Acimovic

Reputation: 506

If you post your image as a byte array, you should be able to turn it in Base64 format and display in view :

<img src="data:image;base64,@Convert.ToBase64String(item.ProductImageUrl)" />

Worth a shot.

Upvotes: 0

Related Questions