Reputation: 571
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
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
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
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
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