I have created a view bag in controller's post back event which stores the image path.
Then,i used this view bag value in image src attribute.But image is not displayed.
Model:
public class FileManagement
{
public string FileName { get; set; }
public string Path { get; set; }
}
Code for uploading image
[HttpPost]
public ActionResult UploadPic(FileManagement fmanage, HttpPostedFileBase file)
{
string email = User.Identity.Name;
if (file != null && file.ContentLength > 0)
{
var FileName = string.Format("{0}.{1}", Guid.NewGuid(), Path.GetFileName(file.FileName));
var path = Path.Combine(Server.MapPath("~/Content/Uploads"), FileName);
file.SaveAs(path);
using (var session = DocumentStore.OpenSession("RavenMemberShip"))
{
var query = from q in Session.Query<Registration>() where q.Email == email select q;
if (query.Count() > 0)
{
foreach (var updated in query)
{
updated.FileName = FileName;
updated.Path = path;
session.SaveChanges();
}
}
}
}
else ModelState.AddModelError("", "Remove the errors and try again");
return View();
}
Controller
[HttpGet]
public ActionResult DisplayPic()
{
ViewBag.Imagepath = "C:\\Users\\Wasfa\\Documents\\Visual Studio 2012\\Projects\\MvcMembership\\MvcMembership\\App_Data\\Uploads\\annonymous.jpg";
return View();
}
[HttpPost]
public ActionResult DisplayPic(FileManagement fm)
{
using (var session = DocumentStore.OpenSession("RavenMemberShip"))
{
string ipath;
// string UserName = User.Identity.Name;
string UserName = "wasfa_anjum#yahoo.com";
var getPath = from p in Session.Query<Registration>()
where p.Email == UserName
select p;
if (getPath.Count() > 0)
{
foreach (var imgpath in getPath)
{
ipath = imgpath.Path;
ViewBag.Imagepath = ipath;
}
}
}
return View();
}
View:
#using (Html.BeginForm())
{
<div>
<img src="#Url.Content(ViewBag.Imagepath)" width="200" height="200" />
</div>
<input type="submit" value="Display" />
}
In my opinion, your problem is not to do with ASP.NET MVC, but you are missing some HTML/Web basics.
You have to understand that when you want to access a resource (html file, image etc), you have to use the HTTP URI syntax. You cannot and should not use your Windows file system path syntax.
Using something like C:\\Users\\Wasfa\\Documents\\Visual Studio 2012\\Projects\\MvcMembership\\MvcMembership\\App_Data\\Uploads\\annonymous.jpg" in HTML is completely wrong. To understand it better, imagine when you have your ASP.NET MVC website up and running for its users to access, they will come to you web page and the HTML downloaded on their browser will be:
<img src="C:\Users\Wasfa\Documents\Visual Studio 2012\Projects\MvcMembership\MvcMembership\App_Data\Uploads\annonymous.jpg" />
Do you think that path will exist on their computers? No.
So, to instruct the <img /> tag to fetch the image from the server, you have to specify either a full HTTP URI, for example:
<img src="http://mywebsite.com/Content/Uploads/annonymous.jpg" />
or a relative HTTP URI (which is like a relative path from your web site's root folder):
<img src="~/Content/Uploads/annonymous.jpg" />
Another problem with your approach is that App_Data is a special folder and its contents are not accessible from the browser by default. So, as per ASP.NET MVC convention, you can create a Content folder in your project to hold your static images and other static content like style sheels, and then link to them.
Once you do that, no one stops you from providing the relative path for your default image as a ViewBag property.
ViewBag.Imagepath = "~/Content/Uploads/annonymous.jpg";
And then use it the way you want:
<img src="#Url.Content(ViewBag.Imagepath)" width="200" height="200" />
I also expect the paths you subsequently fetch from the database, also follow this scheme.
path for image must have forward slash (/),
more over this type of path might work only in your local system and not in your server.
Try using Server.MapPath to fetch your path
Using ViewBag for displaying image is a bad idea, consider using your model property to store the image path and use
<img src="#Url.Content(Model.ImagePath)" alt = "Image" />
EDIT :
Controller:
[HttpGet]
public ActionResult DisplayPic()
{
FileManagement fm = new FileManagement();
fm.Path = "Your image path";
return View(fm);
}
View :
`<img src="#Url.Content(Model.path)" alt = "Image" />`
didn't check the code, but this should work.
It looks like you only really need one result for getPath, this might clean your code up a bit
var imgPath= Session.Query<Registration>()
.FirstOrDefault(p => p.Email == UserName)
.Select(i => i.Path);
if (!string.IsNullOrEmpty(imgPath)
ViewBag.Imagepath = imgPath;
else
{
//no user found, handle error
}
Other than that your code looks fine, can you debug through your application and see what imgPath is equal to after your query is run?
In case, if the image to be displayed when export to excel from the web page.
Use the server path of the image, otherwise, the image would not be loaded from the assembly image folder.
Example:
config:
<add key="LogoPath" value="http:\\mysite\\images\\" />
code:
companyLogo = string.Format("{0}myLogo.png", System.Web.Configuration.WebConfigurationManager.AppSettings["LogoPath"]);
HTML:
<img src='" + #Url.Content(companyLogo) + "' />
Related
I am trying to get image files from the database and bind it to a KendoUI ListView. The problem is that it is not showing images at all.
This is what I have done:
View
<script type="text/x-kendo-tmpl" id="template">
<div class="product">
<img src="#Url.Content("#:PhotoID# + #:MIMEType#")" />
</div>
</script>
<div id="imageListView2" class="demo-section">
#(Html.Kendo().ListView<WorcesterMarble.ViewModels.PhotosViewModel>()
.Name("listView")
.TagName("div")
.ClientTemplateId("template")
.DataSource(dataSource =>
{
dataSource.Read(read => read.Action("GetImages", "StockReceiptsGrid").Data("passStockIDToListView"));
dataSource.PageSize(1);
})
.Pageable()
.Selectable(selectable => selectable.Mode(ListViewSelectionMode.Multiple))
//.Events(events => events.Change("onChange").DataBound("onDataBound"))
)
</div>
Controller
public JsonResult GetImages([DataSourceRequest] DataSourceRequest request, int stockReceiptID)
{
var photos = _stockPhotosRepository.GetStocReceiptkPhotos(stockReceiptID).ToList();
var photosList = new List<PhotosViewModel>();
//var photosList = new List<FileContentResult>();
if (photos.Count != 0)
{
foreach (var stockPhoto in photos)
{
var photoVm = new PhotosViewModel();
photoVm.PhotoID = stockPhoto.PhotoID;
photoVm.Image = stockPhoto.ImageData;
photoVm.MIMEType = stockPhoto.MIMEType;
// FileContentResult file = File(stockPhoto.ImageData, stockPhoto.MIMEType);
photosList.Add(photoVm);
}
return Json(photosList.ToList(), JsonRequestBehavior.AllowGet);
}
else
{
return null;
//FilePathResult file = this.File("/Content/Images/80.jpeg", "image/jpeg");
//return file;
}
return null;
}
Photo View Model:
public class PhotosViewModel
{
public int PhotoID { get; set; }
public byte[] Image { get; set; }
public string MIMEType { get; set; }
public int StockReceiptID { get; set; }
}
I am not sure if the problem is caused by the image url setting in the template. as you see it is not actually a url because the image is not saved anywhere except from the database. this is a screenshot of how the listview looks like; simply blank even though there must 15 images displayed!
Please let me know any clues or solutions to this problem.
I know this is a bit older, but what you need to do is change the line return Json(photosList.ToList(), JsonRequestBehavior.AllowGet); to the following:
return Json(photosList.ToDataSourceResult(request),
JsonRequestBehavior.AllowGet);
If the method ToDataSourceResult is not recognized, you have to add
using Kendo.Mvc.Extensions;
on top of your document.
It looks like you're missing a return in your controller (just before the end of your if)
return Json(photosList.ToList(), JsonRequestBehavior.AllowGet);
EDIT
Also, I noticed this:
<img src="#Url.Content("#:PhotoID# + #:MIMEType#")" />
Shouldn't that be:
<img src="#Url.Content("#:ImageData#")" />
or something similar?
It might be to late to answer, but your issue is that the json data being sent back to your view is to large so your images are not showing, rather save your images to a file and then render your images via a URL.
I have a place holder for a profile photo.I want it to get profile image from database (this works OK)<img src="#Url.Action("Thumbnail", "Photo", new { id = Model.Mebrief.myGuid, size = "small" })" alt="#Model.UserName" width="150" height="150"/>.
Problem:
If there is no profile image ,it should get default place holder image located here:
<img src="#Url.Content("~/Content/profile-template/img/friend_avatar_default.jpg")" alt="crazy" width="150" height="150"/>
All these are supposed to show in a div below:
<div id="profile"> </div>
NOTE: I am using .cshtml razer page.
You could try something like this in your controller.
public ActionResult Photo(int photoId)
{
MyPhoto photo = null;
try
{
MyPhoto = db.GetMyPhotoById(photoId);
return new FileStreamResult(new MemoryStream(photo.Image), photo.ImageMimeType);
}
catch (Exception ex)
{
//use the default image
return new FilePathResult(Url.Content("~/Content/profile-template/img/friend_avatar_default.jpg"), "image/jpg");
}
}
It would be helpful to see what you are doing in your controller, but I'm guessing you are returning a FileStreamResult from the bytes you get back from the database.
Hope this helps.
below is not a valid razor syntax but just an idea - Use ternary operator
if true ? new image : default image
Model != null
?
img src="#Url.Action("Thumbnail", "Photo", new { id = Model.Mebrief.myGuid, size = "small" })" alt="#Model.UserName" width="150" height="150"/>"
:
img src="#Url.Content("~/Content/profile-template/img/friend_avatar_default.jpg")" alt="crazy" width="150" height="150"/>
I have same action in a controller that fetch from db for example a Employee with a name, age, image (byte[]).
So I store the info in ViewBag. Then in the View the specific code for the image is:
<img src="#ViewBag.Image" alt="Logo" />
But when I see the content of the response I have:
<img src="System.something.FileContentResult" alt="Logo" />
I have seen a lot of examples that gets the FileContentResult from a specific Action in a Controller for example:
(The code is an example only)
public ActionResult GetEmployeeImage (int id){
byte[] byteArray = GetImageFromDB(id);
FileContentData file = new File (byteArray,"image/jpg");
return file;
}
And then render the image with:
<img src="#Url.Action("GetEmployeeImage", "Home", new { id = ViewBag.Id })" alt="Em" />
But I dont want that because I already have the image.
How can I render it to the View throw the ViewBag?
Thanks!
PD: Rendering image in a View is the same but was not concluded
One possibility is to use the data URI scheme. Bear in mind though that this will work only on browsers that support it. The idea is that you would embed the image data as base64 string into the src attribute of the img tag:
<img src="data:image/jpg;base64,#(Html.Raw(Convert.ToBase64String((byte[])ViewBag.Image)))" alt="" />
If on the other hand you want a solution that works in all browsers you will have to use a controller action to serve the image. So in the initial request fetch only the id, name and age properties of the employee and not the image. Then write a controller action that will take the employee id as parameter, query the database, fetch the corresponding image and return it as file result. Then inside the view point the src attribute of the img tag to this controller action.
Based on the answer of #darin , if any one wants to make it via calling a controller's action:
public FileContentResult GetFileByID(string ID)
{
try
{
// Get the object from the db
Ent ent = Biz.GetPatientsByID(ID);
// Convert the path to byte array (imagepath is something like: \\mysharedfolder\myimage.jpg
byte[] doc = EFile.ConvertToByteArray(ent.ImagePath);
string mimeType = File(doc, MimeMapping.GetMimeMapping(Path.GetFileName( ent.ImagePath))).ContentType;
Response.AppendHeader("Content-Disposition", "inline; filename=" + Path.GetFileName(ent.ImagePath));
return File(doc, mimeType);
}
catch (Exception ex)
{
throw ex;
}
}
In the front end:
<img id="ItemPreview" src="#Url.Action("GetFileByID","Patient", new {ID= Model.ID })" alt="" width="350" height="350" />
Where Patient is the controller name.
Well, this newbie is doing something wrong when displaying images uploaded to the server:
model:
public class Person
{
public int ID { get; set; }
public string Name { get; set; }
public string ImageUrl { get; set; }
}
controller (upload - called by the [HttpPost] public ActionResult Create):
public void Upload(Person person)
{
var image = WebImage.GetImageFromRequest();
var filename = Path.GetFileName(image.FileName);
var path = Path.Combine(Server.MapPath("~/App_Data/Uploads/Fotos"), filename);
image.Save(path);
person.ImageUrl = Url.Content(Path.Combine("~/App_Data/Uploads/Fotos", filename));
}
create view:
...
#using (Html.BeginForm("Create", "Person", FormMethod.Post, new { #encType = "multipart/form-data" }))
{
...
#FileUpload.GetHtml(initialNumberOfFiles: 1, allowMoreFilesToBeAdded: false, includeFormTag: false, uploadText: "image")
...
<div>
<input type="submit" value="Create" /> |
#Html.ActionLink("Back", "Index")
</div>
}
So far, so good, the image is uploaded to the folder and the url is saved
Now, I want to see it in the Detail View
detail view:
<div class="display-foto">
<img src="#Url.Content(Server.MapPath(Model.ImageUrl))" alt="IMAGE" />
</div>
Viewing the generated code, everything seems to be alright:
<img src="D:\Users\x\Documents\Visual Studio 2010\Projects\CMI_AD\CMI_AD\App_Data\Uploads\Fotos\_nofoto.jpg" alt="IMAGE" />
But the fact is that nothing appears on the screen except the text "IMAGE".
What am I doing wrong?
P.S. I've tried without the Server.MapPath, using the relative address "~\App_Data\Uploads\Fotos_nofoto.jpg" and the result is the same.
--- EDIT ---
#kmcc049: I've tried your suggestion creating a helper
public static class MyHelpers
{
public static IHtmlString MyImage(this HtmlHelper htmlHelper, string url)
{
var urlHelper = new UrlHelper(htmlHelper.ViewContext.RequestContext);
var img = new TagBuilder("img");
img.Attributes["alt"] = "[IMAGE]";
img.Attributes["src"] = UrlHelper.GenerateContentUrl(url, htmlHelper.ViewContext.HttpContext);
return MvcHtmlString.Create(img.ToString(TagRenderMode.SelfClosing));
}
}
the call in the view:
#Html.MyImage(Model.ImageUrl)
the generated code is
<img alt="[IMAGE]" src="/App_Data/Uploads/Fotos/_nofoto.jpg" />
but the result is the same: no image :(
--- SOLVED ---
Apparently the App_Data is not a good location to save uploaded files because accessing them will result an Error 403 - Forbidden. I move the files to ~/Uploads/Fotos and it works.
That's not a valid HTTP path. That's the path to the folder on your computer.
try the UrlHelper.GenerateContentUrl() method instead
http://msdn.microsoft.com/en-us/library/system.web.mvc.urlhelper.generatecontenturl.aspx
I have implemented a file upload for images using ASP.NET Mvc 3 and the Microsoft.Web.Helpers NuGet package. The implementation is quit simple as it allows you to browse for a file and upload it to a specified directory.
Here is what I have for my image upload solution using ASP.NET MVC 3 and the Microsoft.Web.Helpers NuGet plugin.
Now the ViewModel code
namespace MvcImageUpload.Models {
public class ImageUploadViewModel {
[UIHint("UploadedImage")]
public string ImageUrl { get; set; }
public string ImageAltText { get; set; }
}
}
Now for the controller I've simply dropped this into the Home controller, since this is just a mock project to get it working. I just added an ActionResult which takes an ImageUploadViewModel as a parameter.
public ActionResult Upload(ImageUploadViewModel model) {
var image = WebImage.GetImageFromRequest();
if (image != null) {
if (image.Width > 500) {
image.Resize(500, ((500 * image.Height) / image.Width));
}
var filename = Path.GetFileName(image.FileName);
image.Save(Path.Combine("../Uploads/Images", filename));
filename = Path.Combine("~/Uploads/Images", filename);
model.ImageUrl = Url.Content(filename);
model.ImageAltText = image.FileName.Substring(0, image.FileName.Length - 4);
}
return View("Index", model);
}
My view for the uploading of images is simple, it has an Html.BeginForm, which handles the Post form method and has the encoding type set to be "multipart/form-data".
Then using The Microsoft.Web.Helpers.FileUpload helper, I request an image from the HTTP post and then display it using a custom DisplayFor template, called ImageViewer.
#model MvcImageUpload.Models.ImageUploadViewModel
#using Microsoft.Web.Helpers;
#{
ViewBag.Title = "Index";
}
<h2>Image Uploader</h2>
#using (Html.BeginForm("Upload", "Home", FormMethod.Post,
new { #encType = "multipart/form-data" })) {
#FileUpload.GetHtml(initialNumberOfFiles: 1, allowMoreFilesToBeAdded: false,
includeFormTag: false, addText: "Add Files", uploadText: "Upload File") <br />
<input type="submit" name="submit"
value="Upload Image" text="Upload Images"
style="font-size: .9em;" />
#Html.DisplayFor(x => x, "ImageViewer")<br />
}
Here is what the custom DisplayTemplate looks like
#model MvcImageUpload.Models.ImageUploadViewModel
#if (Model != null) {
<h4 style="color:Green;">Upload Success!</h4>
<p>
Alt Text has been set to <strong>#Model.ImageAltText</strong>
</p>
<img style="padding: 20px;"
src="#(String.IsNullOrEmpty(Model.ImageUrl) ? "" : Model.ImageUrl)"
id="uploadedImage" alt="#Model.ImageAltText"/>
}
This all works and the image gets successfully uploaded to the /Uploads/Images/FileName.extension on the form post.
My question
How can I now have another view to display all the images in that directory, paged and be able to select and delete and image, from the view and the directory?
Also I know the Microsoft.Web.Helpers.FileUpload, supports uploading of multiple files, but I can't find how to implement this with my current solution. Any help would be greatly appriceated.
After you click the Upload Image button, the system should call method which uses Request to get the file.
[HttpPost]
public ActionResult Upload()
{
if(Request.Files != null && Request.Files.Count > 0)
{
for (int i = 0; i < request.Files.Count; i++)
{
var postFile = request.Files[i];
if (postFile != null && postFile.ContentLength > 0)
{
if (postFile.ContentLength < GetMaxRequestLength()) //10MB
{
var file = new ContractAttachment
{
Name = Path.GetFileName(postFile.FileName),
ContentType = postFile.ContentType,
FileLength = postFile.ContentLength,
FileData = GetStreamBuffer(postFile)
};
files.Add(file);
}
}
}
}
}
Hope this help.
what you are asking about looks rather implementation to me then any query....
to Display:
Fetch all images from your Uploads/Images directory through DirectoryInfo... you can search a directory based on some extension and then it will give you a result set which you can iterate.....
Create a view that will display all records as Image links and in controller fetch the resultset to that View.... Bind those records as you want them to display in your VIEW...
System.IO.DirectoryInfo info = new System.IO.DirectoryInfo("your directory path");
var filesinfo= info.GetFiles("*.jpg", System.IO.SearchOption.AllDirectories);
var filenum= filesinfo.GetEnumerator();
while (filenum.MoveNext())
{
//populate some entity like in your case you have ImageUploadViewModel
}
and you can implement you delete logic using Ajax or through post back depends how you want it....
Asp.net MVC Views following this tutorial and it will let you go through this....
but again what you are asking is more like implementation Code not any issue....
The approach I've followed previously, is to persist the file information in a database(or whatever is appropriate). e.g. path, filename, content-type, filesize.
This gives you the most flexibility when editing (alt text, title, description, relation to other objects).
Downloading/Viewing the files can then be handled based on path convention, by creating a ViewImage controller which just gets an image id as parameter.
You can then build a url from the path to the file and you only need to set the content-type.
IIS then does the rest.