Help HttpPostedFileBase returns NULL, I have already tried several things and I have searched in several forums but it works.
This is my code
#using (Html.BeginForm("NuevoProveedor", "Account", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<center>
<form method="post" enctype="multipart/form-data">
<input type="file" id="btnFile" name="file" />
<input type="submit" value="Save" id="btnSave" />
</form>
</center>
}
Controller
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult NuevoProveedor(HttpPostedFileBase file, SubirArchivoModelo model)
{
SubirArchivoModelo modelo = new SubirArchivoModelo();
if (file != null)
{
string Ruta = file.FileName;
return View();
}
else
{
ViewBag.error = "No se pudo generar la carpeta, comunicate con Soporte Tecnico";
return View("UsuarioNuevo");
}
}
you can upload file and save its url in the database table like this:
View:
#using(Html.BeginForm("NuevoProveedor", "Account",FormMethod.Post,new {enctype="multipart/form-data"}))
{
...
<div class="editor-field">
<input type="file" id="btnFile" name="file" />
<input type="submit" value="Save" id="btnSave" />
</div>
...
}
Action:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult NuevoProveedor(SubirArchivoModelo model)
{
if (ModelState.IsValid)
{
if(Request.Files.Count > 0)
{
HttpPostedFileBase file = Request.Files[0];
if (file.ContentLength > 0)
{
var fileName = Path.GetFileName(file.FileName);
model.FileLocation = Path.Combine(
Server.MapPath("~/App_Data/uploads"), fileName);
file.SaveAs(model.FileLocation);
}
//db.TableEntity.Add(model);
//db.SaveChanges();
//return RedirectToAction("Index");
}
}
return View("UsuarioNuevo");
}
Related
Im trying to pass the filepath into my ProfileViewModel but it seems to stay Null even thought the other values are filled.
I have tried debugging it but cant seem to find where its going wrong.
My view
#using (Html.BeginForm("EditProfile", "Profile", FormMethod.Post))
{
#Html.AntiForgeryToken()
#Html.LabelFor(model => model.Photo, htmlAttributes: new { #class = "control-label col-md-2" })
<input asp-for="Photo" type="file"/><br />
<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>
my controller
public IActionResult profile()
{
return View();
}
private readonly IHostingEnvironment he;
public ProfileController(IHostingEnvironment e)
{
he = e;
}
[HttpPost]
public ActionResult EditProfile(ProfileViewModel profile)
{
string ID = Request.Cookies["UserID"];
if (ModelState.IsValid)
{
var Photo = profile.Photo;
var FileName = Path.Combine(he.WebRootPath, Path.GetFileName(Photo.FileName));
if (logicprofile.logicEditProfile(profile.BIO, profile.Sex, profile.Preffered, FileName, Convert.ToInt32(ID)) == true)
{
profile.Photo.CopyTo(new FileStream(FileName, FileMode.Create));
ViewBag.Message = "Profile Updated";
return View("profile", profile);
}
else
{
ViewBag.Message = "Something went wrong";
return View("profile", profile);
}
}
else
{
return View("profile", profile);
}
}
ViewModel
[DisplayName("A picture of you!")]
public IFormFile Photo { get; set; }
I expect my pictures to be saved in a folder and the path to a database so I can use them as profile pictures.
You should use enctype in form for passing file type data.
#using (Html.BeginForm("EditProfile", "Profile", FormMethod.Post, new { enctype = "multipart/form-data" }))
I'm just trying to make an Edit page for my Identity database. I'm using Razor Pages, and I'm new to it. I found some solutions for MVC, but they don't really work for me because of using Views and other stuff like Controllers. I have a main page Index.cshtml, where I can choose the users from a list like the image below
And delete them by clicking a submit button.
I handeled deletion like this:
CSHTML file:
<button type="submit" class="btn btn-sm btn-danger" asp-route-id="#user.Id" asp-page-handler="Del">Del</button>
<button type="submit" class="btn btn-sm btn-primary" asp-route-id="#user.Id" asp-page-handler="Change">Change</button>
CSHTML.CS file:
public ApplicationUser ApUser { get; set; }
public async Task<ActionResult> OnPostDel(string id)
{
ApUsers = _userManager.Users.ToList();
ApUser = await _userManager.FindByIdAsync(id);
if (ApUser != null)
{
IdentityResult result = await _userManager.DeleteAsync(ApUser);
}
//return RedirectToAction("UserChange/Index");
return RedirectToPage("Index");
}
And it works just fine by me, but I need to Edit too. So my Edit POST method in Index.cshtml.cs looks like:
public async Task<ActionResult> OnPostChange(string id)
{
ApUsers = _userManager.Users.ToList();
ApUser = await _userManager.FindByIdAsync(id);
if (ApUser == null)
{
return NotFound();
}
else return RedirectToPage("Edit");
}
And my Edit.cshtml.cs look like this:
<form asp-action="Edit" asp-controller="Users">
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<input type="hidden" asp-for="Id" />
</div>
<div class="form-group">
<label asp-for="Email" class="control-label">Email</label>
<input type="text" asp-for="Email" class="form-control" />
</div>
<div class="form-group">
<label asp-for="Score" class="control-label">Score</label>
<input type="number" asp-for="Score" class="form-control" />
</div>
...
<div class="form-group">
<input type="submit" asp-page-handler="Edit" value="Save" class="btn btn-default" />
</div>
</form>
And Edit.cshtml.cs:
public async Task<IActionResult> OnPostEdit(string id)
{
if (ModelState.IsValid)
{
ApUser = await _userManager.FindByIdAsync(id);
if (ApUser != null)
{
ApUser.Email = Email;
ApUser.UserName = Email;
ApUser.Score = Score;
ApUser.Position = Position;
ApUser.Sequence = Sequence;
var result = await _userManager.UpdateAsync(ApUser);
if (result.Succeeded)
{
return RedirectToAction("Index");
}
else
{
foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
}
}
}
}
return RedirectToAction("Index");
}
And it doesn't work of course. I'm just trying to remake some MVC example to Razor Pages. Maybe you have better solutions for this, but I really stuck here.
So, yeah, I just made a button on my Index.cshtml page like this, it provides asp-route-id to Edit page:
<a asp-page="Edit" class="btn btn-sm btn-primary" asp-route-id="#user.Id">Edit</a>
Made an InputModel on Edit.cshtml.cs file:
public InputModel Input { get; set; }
public class InputModel
{
[Required(ErrorMessage ="{0} не может быть пустым")]
[EmailAddress(ErrorMessage ="Неверный формат {0}")]
[Display(Name = "Email")]
public string Email { get; set; }
[Required(ErrorMessage = "Введите {0}")]
[StringLength(5, ErrorMessage = "{0} должна быть из {1} символов", MinimumLength = 5)]
[Display(Name = "Последовательность")]
public string Sequence { get; set; }
...
}
Just added in Edit.cshtml file #page "{id}", to provide it through previous page
OnPost method provides User changes from the model:
public async Task<IActionResult> OnPostAsync(string id)
{
ApUser = await _userManager.FindByIdAsync(id);
if (!ModelState.IsValid)
{
return Page();
}
ApUser.Email = Input.Email;
ApUser.Score = Input.Score;
ApUser.Sequence = Input.Sequence;
ApUser.Position = 0;
await _userManager.UpdateAsync(ApUser);
Message = ApUser.Email;
return RedirectToPage("Index");
}
And the I just use a model in Edit.cshtml
<form method="post" asp-route-id="#Model.ApUser.Id">
<div class="form-group">
<label asp-for="Input.Email"></label>
<input asp-for="Input.Email" class="form-control" value="#Model.ApUser.Email.ToString()" />
<span asp-validation-for="Input.Email" class="text-danger"></span>
</div>
...
<button type="submit" class="btn btn-default">Save</button>
</form>
I have tried my best however HttpPostedFileBase filee is always null
Controller Action
public ActionResult UploadFile(HttpPostedFileBase filee)
{
try
{
if (filee.ContentLength > 0)
{
string _FileName = Path.GetFileName(filee.FileName);
string _path = Path.Combine(Server.MapPath("~/UploadedFiles"), _FileName);
filee.SaveAs(_path);
}
ViewBag.Message = "File Uploaded Successfully!!";
return View();
}
catch
{
ViewBag.Message = "File upload failed!!";
return View();
}
}
Razor View
#{
ViewBag.Title = "UploadFile";
}
<h2>UploadFile</h2>
#using (Html.BeginForm("UploadFile", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div>
#Html.TextBox("file", "", new { type = "file" }) <br />
<input type="submit" value="Upload" />
#ViewBag.Message
</div>
}
Either change the name of parameter in public ActionResult UploadFile(HttpPostedFileBase filee) to public ActionResult UploadFile(HttpPostedFileBase file) or change the input name #Html.TextBox("file", "", new { type = "file" }) to #Html.TextBox("filee", "", new { type = "file" }).
You have to use same name of yor input field as your HttpPostedFileBase object name while you are working on loosly type view !
Example :
#{
ViewBag.Title = "UploadFile";
}
<h2>UploadFile</h2>
#using (Html.BeginForm("UploadFile", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div>
#Html.TextBox("filee", "", new { type = "file" }) <br />
<input type="submit" value="Upload" />
#ViewBag.Message
</div>
}
Or If you don't want to use same names ?
you just have to use a tightly coupled view type view
Tightly
Example:
#model PROJECTNAME.Models.MODELNAME
#{
ViewBag.Title = "UploadFile";
}
<h2>UploadFile</h2>
#using (Html.BeginForm("UploadFile", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div>
#Html.TextBox(model => model.YOURCOLUMNNAME , "", new { type = "file" }) <br />
<input type="submit" value="Upload" />
#ViewBag.Message
</div>
}
I am having some difficulties in validation of form.
Since I want to populate combobox from database (another table, I'm using viewbags to do this), is there a way to use ComboBoxFor in this case so I could use System.ComponentModel.DataAnnotations and jquery.validate.js?
View:
#model MyProject.OpenAccess.Document
#using (Html.BeginForm("CreateDocument", "Create", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<label>Select file:</label><br />
<input type="file" name="file" /><br />
<label>Filetype</label><br />
#Html.DropDownList("fileType", (IEnumerable<SelectListItem>)ViewBag.ListFiletypes, "-Filetypes", new { #class = "filetype-cb" }) <br />
<input type="submit" value="Add"/>
}
Controller:
public ActionResult CreateDocument(HttpPostedFileBase file, string fileType)
{
if (file != null && file.ContentLength > 0)
{
Document doc = new Document()
{
Filetype = fileType
}
if (this.TryValidateModel(doc))
{
this.dbContext.Add(doc);
this.dbContext.SaveChanges();
id = doc.ID;
//save document using document ID
}
}
}
EDIT:
Here is my current implementation of this:
Layout.cshtml
Remember to add:
<script src="#Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
View
#model MyProject.OpenAccess.Document
#using (Html.BeginForm("CreateDocument", "Create", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<label>Select file:</label><br />
<input type="file" data-val="true" data-val-required="Please select a file!" name="file" /><br />
<label>Filetype</label><br />
#Html.DropDownListFor(m => m.FileType, (IEnumerable<SelectListItem>)ViewBag.ListFiletypes, "", new { #class = "filetype-cb" })
<input type="submit" value="Add"/>
}
Controller
[HttpGet]
public ActionResult CreateDocument()
{
ViewBag.ListFiletypes = new SelectList(this.dbContext.ListFiletypes.ToList(), "FileType", "FileType");
//Populate dropdownlist from database
}
[HttpPost]
public ActionResult CreateDocument(HttpPostedFileBase file, Document doc)
{
if (file != null && file.ContentLength > 0)
{
if (this.TryValidateModel(doc))
{
this.dbContext.Add(doc);
this.dbContext.SaveChanges();
id = doc.ID;
//save document using document ID
}
}
}
Model
public partial class Document
{
private int _iD;
public virtual int ID
{
get
{
return this._iD;
}
set
{
this._iD = value;
}
}
private string _fileType;
[Required(ErrorMessage = "Required!")]
public virtual string FileType
{
get
{
return this._fileType;
}
set
{
this._fileType = value;
}
}
}
Is there good reasons to use Viewmodel over Viewbag to populate DropDownListFors (found this from http://www.codeproject.com/Articles/687061/Multiple-Models-in-a-View-in-ASP-NET-MVC-MVC)?
Only problem with this implementation is that I can't validate file on client-side (so user couldn't post empty file).
EDIT: Got this working by just adding:
<input type="file" data-val="true" data-val-required="Please select a file!" name="file" />
Normally you have 3 different parts, which build a proper implementation of your scenario.
The ViewModel:
In a proper implementation, you got for every view its own Viewmodel. In your case that would be something like this:
public class CreateDocumentViewModel
{
[Required]
public IEnumerable<SelectListItem> filetypes { get; set; }
// Maybe some more attributes you need in the view?
}
Note: here you can use the DataAnnotations you want.
The View:
The view contains the actual data in the dropdown.
#model CreateDocumentViewModel
#using (Html.BeginForm("CreateDocument", "Create", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<label>Select file:</label><br />
<input type="file" name="file" /><br />
<label>Filetype</label><br />
#Html.DropDownListFor(model => model.filetypes, model.filetypes, "-Filetypes", new { #class = "filetype-cb" })
<br />
<input type="submit" value="Add"/>
}
The controller:
The controller you need, has 2 actions. A GET- and a POST-action.
[HttpGet]
public ActionResult CreateDocument()
{
CreateDocumentViewModel model = new CreateDocumentViewModel();
model.filetypes = FillFileTypesFromDB; // Here you fill the data for the dropdown!
return View(model);
}
Finally you need the POST-action which saves back to your db.
[HttpPost]
public ActionResult CreateDocument(HttpPostedFileBase file, string fileType)
{
if (file != null && file.ContentLength > 0)
{
Document doc = new Document()
{
Filetype = fileType
}
if (this.TryValidateModel(doc))
{
this.dbContext.Add(doc);
this.dbContext.SaveChanges();
id = doc.ID;
//save document using document ID
}
}
}
I hope I fully understood your problem and it helps solving it.
This is my code:
#using (Html.BeginForm("UploadImages", "Administration", new { _id = Model.Album.AlbumID, enctype = "multipart/form-data" }, FormMethod.Post))
{
<input type="file" name="fileUpload" id="file1" /><br />
<input type="file" name="fileUpload" id="file2" /><br />
<input type="file" name="fileUpload" id="file3" /><br />
<input name="addPhoto" type="submit" value="Добавить фото" />
}
[Authorize]
[HttpPost]
public ActionResult UploadImages(int _id, IEnumerable<HttpPostedFileBase> fileUpload)
{
gb_albumdbEntities1 entityes = new gb_albumdbEntities1();
foreach (var file in fileUpload)
{
if (file == null) continue; // **<---fileUpload items is always null!**
string path = AppDomain.CurrentDomain.BaseDirectory + "Photos/";
if (Path.GetFileName(file.FileName) != null)
{
string filename = file.GetHashCode().ToString();
string fullpath = Path.Combine(path, filename);
file.SaveAs(fullpath);
entityes.Photos.AddObject(new Photo() { AlbumID = _id, PhotoUrl = #"http://site.ru/Photos/" + filename });
}
}
entityes.SaveChanges();
return RedirectToAction("AlbumEdit", new { id = _id });
}
fileUpload items is always null. Where is the problem?Oo
UPD: calculated result post url:
http://localhost:56193/Administration/UploadImages?_id=4&enctype=multipart%2Fform-data
your list if file inputs need to be numbered for model binding to work. In the simplest form your view should look something like this:
<html>
<head>
<title>Index</title>
</head>
<body>
<div>
#using (Html.BeginForm("Index", "Upload", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
for (int i = 0; i < 3; i++)
{
#Html.TextBox(string.Format("fileUpload[{0}]", i), null, new { type="file" })<br />
}
<input name="submit" type="submit" value="Go" />
}
</div>
</body>
</html>
and your controller:
public class UploadController : Controller
{
//
// GET: /Upload/
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(IEnumerable<HttpPostedFileBase> fileUpload)
{
return View();
}
}
Try the following post which I've used myself before. Worked for me.
http://haacked.com/archive/2010/07/16/uploading-files-with-aspnetmvc.aspx