I have a MultipartForms in Which I Could upload an Image and other form values.While, the form values are rightfully received through the FormCollection Property whereas the Upload file always shows the null value in HttpPostedFileBase Property.I go through forums but I couldn't get Where went Wrong. Here, Is What I done Please go through it and Said what Went Wrong.Thanks friend.
enter code here
cshtml:
#using (Html.BeginForm("Create", "StaffRegistration", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<input type="file" name="StaffImage" id="StaffImage" />
}
Controller
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(FormCollection collection,HttpPostedFileBase File)
{
try
{
// TODO: Add insert logic here
StaffRegistration StaffReg = new StaffRegistration();
StaffReg.FirstName = collection["FirstName"].ToString();
StaffReg.LastName = collection["LastName"].ToString();
StaffReg.DateOfBirth = DateTime.Parse(collection["DateofBirth"]);
StaffReg.Nationality = collection["Nationality"].ToString();
StaffReg.Gender = collection["Gender"].ToString();
StaffReg.MaritalStatus = collection["MaritalStatus"].ToString();
StaffReg.BloodGroup = collection["BloodGroup"].ToString();
StaffReg.StaffName = collection["StaffName"].ToString();
StaffReg.MiddleName = collection["MiddleName"].ToString();
HttpPostedFileBase file = Request.Files["StaffImage"];
StaffRegistrationBusSer StaffRegBusSer = new StaffRegistrationBusSer();
StaffRegBusSer.AddStaffReg(StaffReg,file);
return RedirectToAction("Index");
}
DataLayer
public bool AddStaffRegistraiton(StaffRegistration staffRegistration,HttpPostedFileBase File)
{
staffRegistration.StaffImage = ConvertToByte(File);
using(SqlConnection Con = new SqlConnection(ConnectionString))
{
SqlParameter paramImage = new SqlParameter();
paramImage.ParameterName = "#StaffImage";
paramImage.Value = staffRegistration.StaffImage;
Cmd.Parameters.Add(paramImage);
Con.Open();
Cmd.ExecuteNonQuery();
}
return true;
}
ConvertToByte function:
public byte[] ConvertToByte(HttpPostedFileBase Image)
{
byte[] imagebyte = null;
BinaryReader Reader = new BinaryReader(Image.InputStream);
imagebyte = Reader.ReadBytes((int)Image.ContentLength);
return imagebyte;
}
cshtml page:
#using (Html.BeginForm("Index", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div class="form-group">
#Html.LabelFor(model => model.StaffName, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.StaffName)
#Html.ValidationMessageFor(model => model.StaffName)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="file" name="StaffImage" id="StaffImage" />
</div>
</div>
}
Actually I have to include multipart/form in View level, Instead of the particular upload files.Then, I Modified like this in .cshtml page. Now, my code works fine
Related
I would like the page to saves the uploaded file even if the submit button is clicked at the time where not all the form is filled unless all the form is completed.
<div class="form-group">
#Html.LabelFor(model => model.cvURL, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-lg-10">
#Html.TextBoxFor(model => model.cvURL, new { type = "file" })
#Html.ValidationMessageFor(model => model.cvURL)
</div>
</div>
public ActionResult RegisterCandidates(CandidateRegisteration can, HttpPostedFileBase cvURL)
{
if (ModelState.IsValid)
{
if (CheckFileType(cvURL.FileName))
{
var fileName = Path.GetFileName(cvURL.FileName);
var path = Path.Combine(Server.MapPath("~/CVuploads"), fileName);
can.cvURL = cvURL.FileName;
cvURL.SaveAs(path);
db.CandidateRegisteration.Add(can);
db.SaveChanges();
return RedirectToAction("Index");
}
else
{
ViewBag.emailExists = "Not Right extention";
}
}
return View();
}
Ok So I have been searching all over have come to this little bit of code and got almost everything to work. I can upload an image and save it to the folder that was created. I can save the the other values pass to the database as well. My problem now is that i want to save the file path to the data base so i can call it to display the image on another page. For some reason it will only save the image's name that is being uploaded and not the path.
When i debug it and see what all is getting passed, when i add a watch to
file.SaveAs(pathLoc);
Expression has been evaluated and has no value void
Here is the code I've beed using
Controller
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(ImageInfo info, HttpPostedFileBase file)
{
if (ModelState.IsValid)
{
if (file != null)
{
var pic = Path.GetFileName(file.FileName);
var pathLoc = Path.Combine(Server.MapPath("~/Uploads/") + pic);
file.SaveAs(pathLoc);
info.ImagePath = file.FileName;
db.SaveChanges();
}
return RedirectToAction("Index");
}
return View(info);
}
View
<h2>Create</h2>
#using (Html.BeginForm("Create", "ImageInfoes", null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<div class="form-horizontal">
<h4>ImageInfo</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.ImageName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ImageName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ImageName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ImageSize, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ImageSize, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ImageSize, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ImagePath, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<input id="ImagePath" title="Upload a product image" type="file" name="file" />
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
Model
public partial class ImageInfo
{
public byte id { get; set; }
public string ImageName { get; set; }
public Nullable<long> ImageSize { get; set; }
public string ImagePath { get; set; }
}
Anything would be help full.
If you want, full path you need to combine file path and file name both.
Console.WriteLine(Path.Combine(System.Reflection.Assembly.GetExecutingAssembly().Location, System.IO.Path.GetRandomFileName()));
C:\Users\02483695\Documents\Visual Studio
2015\Projects\ConsoleApplication5\Cons
oleApplication5\bin\Debug\ConsoleApplication5.exe\tv1k1uev.jsq
Also below you may find a sample about file, file directory, file path and file extension.
System.IO.FileInfo fileInfo = new FileInfo("filename.file");
var fileDirectory = fileInfo.DirectoryName;
var fileName = fileInfo.Name;
var fileExtension = fileInfo.Extension;
var filePathandFileNameBoth = fileInfo.FullName;
Console.WriteLine("filePathandFileNameBoth: ");
Console.WriteLine(filePathandFileNameBoth);
Console.WriteLine("-");
Console.WriteLine("fileDirectory:");
Console.WriteLine(fileDirectory);
Console.WriteLine("-");
Console.WriteLine("fileName:");
Console.WriteLine(fileName);
Console.WriteLine("-");
Console.WriteLine(filePathandFileNameBoth == fileDirectory + "\\" + fileName ? fileExtension : "I'm totally wrong");
Console.ReadLine();
as a result:
I'm trying to upload a file alongside with some model information.
In my table I already have a field 'image' (string) to save the relative URL to the image.
But I don't really know how to do the uploading itself.
I've already read a lot off tutorials, but they all use HttpPostedFileBase, which isn't supported anymore?
This is what I have thus far:
Upload page:
#using (Html.BeginForm("Lets", "Create", FormMethod.Post, new { #enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<fieldset>
<div class="form-group">
<div class="mdl-cell col-md-10 mdl-textfield mdl-js-textfield">
#Html.LabelFor(m => m.Lets.Name, new { #class="mdl-textfield__label" })
#Html.TextBoxFor(m => m.Lets.Name, new { #class= "form-control mdl-textfield__input" })
</div>
</div>
<div class="form-group">
<div class="mdl-cell col-md-10 mdl-textfield mdl-js-textfield">
#Html.LabelFor(m => m.Lets.Images)
<input type="file" name="LetsImages" id="m.Lets.Images" /> <br />
</div>
</div>
<div class="form-group">
<div class="mdl-cell col-md-10 mdl-textfield mdl-js-textfield">
#Html.LabelFor(m => m.Lets.Description, new { #class="mdl-textfield__label" })
#Html.TextBoxFor(m => m.Lets.Description, new { #class= "form-control mdl-textfield__input" })
</div>
</div>
<div class="form-group">
<div class="mdl-cell col-md-10 mdl-textfield mdl-js-textfield">
#Html.LabelFor(m => m.Lets.Credits, new { #class="mdl-textfield__label" })
#Html.TextBoxFor(m => m.Lets.Credits, new { #class= "form-control mdl-textfield__input" })
</div>
</div>
<div class="form-group">
<div class="mdl-cell col-md-10">
#Html.LabelFor(m => m.Lets.Group)
#Html.DropDownListFor(m => m.Lets.GroupId, new SelectList(Model.Groups, "Id", "Name"), "-- Selecteer een Groep --", new { #class= "form-control" })
</div>
</div>
#Html.ActionLink("Terug naar het overzicht", "Index", new { }, new { #class= "mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect" })
<input type="submit" value="Save" class="mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect" />
</fieldset>
}
Controller:
[HttpGet]
public IActionResult Create()
{
var model = new LetsViewModel
{
Lets = new Lets(),
Groups = _kletsContext.Groups.AsEnumerable(),
Letses = _kletsContext.Lets.AsEnumerable().OrderBy(m => m.Name)
};
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(LetsViewModel model)
{
LetsViewModel viewModel = null;
try
{
if(!ModelState.IsValid)
throw new Exception("The Lets model is not valid!");
var letsImage = "INSERT LOGIC FOR IMAGEUPLOAD HERE?";
model.Lets.UserId = User.GetUserId();
model.Lets.StatusId = 1;
model.Lets.Images = letsImage;
_kletsContext.Lets.Add(model.Lets);
if (_kletsContext.SaveChanges() == 0)
{
throw new Exception("The Lets model could not be saved!");
}
//Success(CreateMessage(ControllerActionType.Create, "klets", model.Name), true);
return RedirectToAction("Index", "Home");
}
catch(Exception ex)
{
ModelState.AddModelError(string.Empty, "Unable to save changes.");
viewModel = new LetsViewModel
{
Lets = model.Lets,
Letses = _kletsContext.Lets.AsEnumerable().OrderBy(m => m.Name)
};
}
return View(viewModel);
}
I've added the place where I think the logic should come?
So what I want to do is:
Upload the Image to a folder
Rename it
Store the relative path as a string to the db.
Thank you
There is no HttpPostedFileBase in MVC6, you have to use IFormFile like this:
public FileDetails UploadSingle(IFormFile file)
{
FileDetails fileDetails;
using (var reader = new StreamReader(file.OpenReadStream()))
{
var fileContent = reader.ReadToEnd();
var parsedContentDisposition = ContentDispositionHeaderValue.Parse(file.ContentDisposition);
fileDetails = new FileDetails
{
Filename = parsedContentDisposition.FileName,
Content = fileContent
};
}
return fileDetails;
}
You can upload images using handlers , link to tutorials are
http://www.c-sharpcorner.com/blogs/uploading-files-using-jquery-ajax-in-asp-net1
http://www.binaryintellect.net/articles/f2a2f1ee-e18a-416b-893e-883c800f83f4.aspx
http://www.dotnetjalps.com/2011/12/async-file-upload-with-jquery-and.html?m=1
These tutorials are using jquery to pass the image to the handler and then handler saving the image in the folder. You can rename the image before uploading to the folder and get back the saved image name in response and then save image name along with other model properties.
I eventually got it working by:
include using Microsoft.AspNet.Hosting; and using System.IO;
using System.Net.Http.Headers;
Add public IHostingEnvironment _environment { get; set;}
to your controller (I added it to my commoncontroller, and then it's available to me on my controller)
Then in my create:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(LetsViewModel model, IFormFile LetsImages)
{
LetsViewModel viewModel = null;
try
{
if(!ModelState.IsValid)
throw new Exception("The Lets model is not valid!");
if(LetsImages != null)
{
var targetDirectory = Path.Combine(_environment.WebRootPath, string.Format("images/uploads"));
var fileName = ContentDispositionHeaderValue
.Parse(LetsImages.ContentDisposition)
.FileName
.Trim('"');
var savePath = Path.Combine(targetDirectory, fileName);
var relPath = "/images/uploads/" + fileName;
try
{
LetsImages.SaveAs(savePath);
model.Lets.Images = relPath;
}
catch
{
throw new Exception("There was a problem with saving the file!");
}
}
else
{
model.Lets.Images = null;
}
model.Lets.UserId = User.GetUserId();
model.Lets.StatusId = 1;
_kletsContext.Lets.Add(model.Lets);
if (_kletsContext.SaveChanges() == 0)
{
throw new Exception("The Lets model could not be saved!");
}
//Success(CreateMessage(ControllerActionType.Create, "klets", model.Name), true);
return RedirectToAction("Index", "Home");
}
catch(Exception ex)
{
ModelState.AddModelError(string.Empty, "Unable to save changes.");
viewModel = new LetsViewModel
{
Lets = model.Lets,
Groups = _kletsContext.Groups.AsEnumerable(),
Letses = _kletsContext.Lets.AsEnumerable().OrderBy(m => m.Name)
};
}
return View(viewModel);
}
Just make sure you've created the folder where the images should belong, else it's not going to work without any error!
Thanks everybody for your help!
I'm new to asp.net and this is my first application.
I'm developing an application that manages insurance requests. The model Request contains a file upload. the addDemand (adds a request)requires a member(adherent) to be logged in. Every time I try to run the addDemande I get the error:
The model item passed into the dictionary is of type 'System.Collections.Generic.List`1[Mutuelle.Domain.Entities.Demande]', but this dictionary requires a model item of type 'Mutuelle.Domain.Entities.Demande'.
Here's the controller:
public ActionResult AddDemande()
{
Demande demande = new Demande();
return View(demande);
}
[HttpPost]
public ActionResult AddDemande([Bind(Exclude = "fichier")]Demande demande, HttpPostedFileBase fichier)
{
try
{
if (!ModelState.IsValid)
{
return View();
}
else
{
BinaryReader fichierReader = new BinaryReader(fichier.InputStream);
byte[] fichiers = fichierReader.ReadBytes(fichier.ContentLength);
demande.fichier = fichiers;
AdherentDService adherentService = new AdherentDService();
Adherent adherent = (Adherent)Session["logedAd"];
demande.nomBeneficiaire = adherent.nom;
demande.eMailBeneficiaire = adherent.eMail;
demande.beneficiare = adherent;
adherent.listDemandes.Add(demande);
adherentService.Updateadherent(adherent);
demande.beneficiare = adherent;
adherentService.CreateaDemande(demande);
Session.Remove("logedAd");
Session.Add("logedAd", adherent);
return RedirectToAction("Demandes");
}
}
catch
{
return RedirectToAction("Index", "Home");
}
}
And here's the View:
model Mutuelle.Domain.Entities.Demande
#{
ViewBag.Title = "AddDemande";
}
<h2>AddDemande</h2>
#using (Html.BeginForm("AddDemande", "Adherent", FormMethod.Post, new { #enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Demande</h4>
<hr />
#Html.ValidationSummary(true)
<div class="form-group">
#Html.LabelFor(model => model.Nomrubrique, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Nomrubrique)
#Html.ValidationMessageFor(model => model.Nomrubrique)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.fichier, new { #class = "control-label col-md-2" })
<div class="col-md-10">
<input style="margin-left:0px;cursor:pointer;" type="file" name="fichier" id="fichier" />
</div>
</div>
I have the edit view and the edit action in my blog controller.
After I created a post with the "create action" and after I upload the image to the database folder, I update the path on the post.PostImage (string value).
I can see the image in the folder, and I can see the path of my image and I can also see the preview of the picture in the edit view. In my database it saved as (~/Images/PostID/PictureName). But after I edit my post, I want to make a checkbox that if checked I can edit the picture and when is it not checked I delete the picture. I send the parameters, and my problem is that on the debugger I see the "string postimage" as null but on the database table it has the path!
and because of that all of this doesn't work, I don't care about logic, why is it null????
here is my code:
VIEW:
#model WebApplication1.Models.Post
#{
ViewBag.Title = "Edit";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Edit</h2>
#using (Html.BeginForm(Html.BeginForm("Edit", "Blog", FormMethod.Post, new { enctype = "multipart/form-data" })))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Post</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.PostID)
<div class="form-group">
#Html.LabelFor(model => model.PostTitle, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.PostTitle, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.PostTitle, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.PostAuthor, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.PostAuthor, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.PostAuthor, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.WebSite, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.WebSite, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.WebSite, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.PostDate, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.PostDate, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.PostDate, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.PostText, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.PostText, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.PostText, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div>
<b>Upload image:</b>
#if (!Model.PostImage.IsEmpty())
{
#Html.CheckBox("checkImage", true)
<img src="#Url.Content(Model.PostImage)" alt="#Model.PostAuthor" width="300" />
}
else
{
#Html.CheckBox("checkImage", false)
}
</div>
<input type="file" name="file" id="file" />
<!-- Show message of the controller -->
#ViewBag.Message
</div>
<div class="form-group">
#Html.LabelFor(model => model.PostVideo, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.PostVideo, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.PostVideo, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to Posts List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
EDIT ACTION IN BLOG CONTROLLER:
// GET: Blog/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Post post = db.Posts.Find(id);
if (post == null)
{
return HttpNotFound();
}
return View(post);
}
// POST: Blog/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "PostID,PostTitle,PostAuthor,WebSite,PostDate,PostText,PostImage,PostVideo")] Post post, HttpPostedFileBase file, bool checkImage)
{
var fileName = "";
if (ModelState.IsValid)
{
db.Entry(post).State = EntityState.Modified;
if (checkImage == true)
{
//Check if there is a file
if (file != null && file.ContentLength > 0)
{
//Check if there is an image
var supportedTypes = new[] { "jpg", "jpeg", "gif", "png" };
var fileExt = System.IO.Path.GetExtension(file.FileName).Substring(1);
if (!supportedTypes.Contains(fileExt))
{
ViewBag.Message = "Invalid image type. Only the following types (jpg, jpeg, gif, png) are supported";
return View();
}
//Check if there is a file on database
if ( !(String.IsNullOrEmpty(post.PostImage)) )
{
//Delete old file in folder
System.IO.File.Delete(post.PostImage);
//Save new file in folder
var folder = Path.Combine(Server.MapPath("~/Images/"), Convert.ToString(post.PostID));
var path = Path.Combine(folder, fileName);
file.SaveAs(path);
//Save path in database
string targetPath = String.Concat("~/Images/", Convert.ToString(post.PostID), "/", fileName);
post.PostImage = targetPath;
}
//No file in database
else
{
var folder = Path.Combine(Server.MapPath("~/Images/"), Convert.ToString(post.PostID));
var path = Path.Combine(folder, fileName);
file.SaveAs(path);
//Save path in database
string targetPath = String.Concat("~/Images/", Convert.ToString(post.PostID), "/", fileName);
post.PostImage = targetPath;
}
}
//Checkbox is checked but not file uploaded
else
ViewBag.Message = "Checkbox is checked, please upload an image";
return View();
}
else
{
//Checkbox is not checked - Delete the image from database
if( !(String.IsNullOrEmpty(post.PostImage)) )
{
//Delete old file in folder
try
{
System.IO.File.Delete("\a.txt");
post.PostImage = null;
}
catch (System.IO.IOException e)
{
Console.WriteLine(e.Message);
}
}
db.SaveChanges();
return RedirectToAction("Index");
}
}
return View(post);
}
Render the postImage field
#Html.EditorFor(model => model.PostImage, new { htmlAttributes = new { #class = "form-control" } })
So from what I have read recently, do not pass your Entity Framework model directly into your view. Create a separate ViewModel. On GET, Construct this ViewModel based on your EF model, and on POST, extract the information you need from your ViewModel and update your EF model that is in the database.
In your View, you don't have a EditorFor() or HiddenFor() for the image URL, and that is why on your POST it will be null.
This is EXACTLY why you want to use ViewModels instead of directly using EF models in your view so you can have a separate view model that only contains property that needs to be edit/updated/displayed, while properties from the entities that needs to be remained untouched will remain untouched.