I don't know what I'm missing, but I need to upload a file using C# MVC 3. I followed instructions here in SO, but the file is always empty.
Here is my actual testing code:
HTML
#using (Html.BeginForm("Prc", "Upload", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<input type="file" name="file" id="file" />
<input type="submit" value="submit" />
}
Controller
[HttpPost]
public ActionResult Prc(HttpPostedFile file)
{
if (file != null && file.ContentLength > 0)
{
var filename = System.IO.Path.GetFileName(file.FileName);
var path = System.IO.Path.Combine(Server.MapPath("~/Content/Images"), filename);
file.SaveAs(path);
}
return RedirectToAction("Index");
}
When I run the web app, I attach a file, and click Submit. But when I reach the Controller, the file object is null. Always null. I tried an XML file, a JPEG file, and a GIF file but none of them worked.
Should I configure something else besides just these codes?
Thanks
In MVC you need to use HttpPostedFileBase instead of the HttpPostedFile:
[HttpPost]
public ActionResult Prc(HttpPostedFileBase file)
{
//...
}
One more thing might trip you up.
Using asp.net mvc 3 razor, I was just surprised to discover that the name of the HttpPostedFileBase variable passed to the controller method must match the id and name of the file input tag on the the view. Otherwise asp.net passes null for the HttpPostedFileBase variable.
For example, if your file input looks like this: < input type="file" name="filex" id="filex" />
And your controller method looks like this:
public ActionResult Uploadfile(HttpPostedFileBase filey)
You'll get NULL for the "filey" variable. But rename "filey" to "filex" in your controller method and it posts the file successfully.
Related
I've created a EditController to fetch and edit the contents of my database in asp.net core project. The Controller is given below:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(MyObject model)
{
if (ModelState.IsValid)
{
await _myObjectRepository.UpdateMsg(model);
return RedirectToAction("Index");
}
return View();
}
I've used the following script tag to reference the ckeditor and kept it on Edit.cshtml.
Inside the form tag I've put the following lines of code to display the editor and display the data from the database inside the editor.
<div class="form-group">
<label asp-for="Body" class="col-sm-2 control-label"></label>
<div class="col-sm-10">
<textarea asp-for="Body" id="editor1" name="editor1"></textarea>
</div>
</div>
<script type="text/javascript">CKEDITOR.replace('Body');</script>
I've no problem displaying the data from database to the editor. But as I try to change the text in the editor, no text would be present in the database.
So tested the code without using the editor i.e. I simply used tag instead of the CKEditor, with usual razor attributes and it worked fine. How can I solve this?
I believe you have a property in the MyObject class to store the content of the CKEditor. Lets suppose "ckEditorVar" is the property to store the ckeditor content. Following code works for me. I hope it will work for you too.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(MyObject model)
{
if (ModelState.IsValid)
{
await _myObjectRepository.UpdateMsg(new MyObject
{
ckeditorVar = Request.Form["editor1"].ToString(),
});
return RedirectToAction("Index");
}
return View();
}
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) + "' />
I am having troubles uploading multiple files using Uploadify in MVC 3.
I select 3 files and post via ajax. I get the files in the controller but there is a problem.
Instead of getting the 3 files in one post, I see the controller gets hit 3 times for 3 files.
I want all 3 files available in the controller in a single post.
Is this possible?
[HttpPost]
public ActionResult UploadFiles()
{
//This always shows one file i debug mode
foreach (string fileName in Request.Files)
{
}
}
I want to process the file in one shot and save them in one shot.
Don't know for Uploadify but with a standard form if you want to upload multiple files at one you would use:
View:
#using (Html.BeginForm("YourAction","YourController",FormMethod.Post,new { enctype="multipart/form-data"})) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Message</legend>
//your html here
//as many input types you would like but they
//must have a same name attribute (files)
<input type="file" name="files"/>
</fieldset>
Controller:
[HttpPost]
public ActionResult YourAction(FormCollection values, IEnumerable<HttpPostedFileBase> files)
{
//do what you want with form values then for files
foreach (var file in files)
{
if (file.ContentLength > 0)
{
byte[] fileData = new byte[file.ContentLength];
file.InputStream.Read(fileData, 0, file.ContentLength);
//do what you want with fileData
}
}
}
So you would use IEnumerable<HttpPostedFileBase> files for multiple files, HttpPostedFileBase file for a single file and you would change the input in the view to
<input type="file" name="file"/>
Regards.
I'm attempting to upload an xml file to my site. However, regardless of which file I attempt to upload, the HttpPostedFileBase element in my code is null. I don't understand why this is. I've followed all the examples I can find on uploading files and it doesn't seem to make any sense. This is the controller method
[HttpPost]
public ActionResult UploadFile(HttpPostedFileBase xmlFile)
{
if (xmlFile != null && xmlFile.ContentLength > 0)
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(xmlFile.InputStream);
// other logic later
return RedirectToAction("Index");
}
return RedirectToAction("UploadFailed");
}
and the cshtml:
#{
ViewBag.Title = "Upload";
}
#using (Html.BeginForm("UploadFile", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<input type="file" name="file" />
<input type="submit" value="OK" />
}
It has a wrong name. The action argument is called xmlFile whereas your file input is called file. You need to be consistent in your naming conventions:
<input type="file" name="xmlFile" />
I also invite you to checkout Phil Haack's blog post on this subject.
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.