I try to upload a file. But if the user doesnt select a file, the same page has to been seen with a message that you have to upload a file.
I have this:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult UploadFile([Bind(Include = "UploadData,Directories")] /*LibraryUploadModel libraryUpload*/ UploadViewModel uploadViewModel, string designId, string folder, FormLibraryEntry formLibraryEntry, string command)
{
//ActionResultSpecification result = SfsHelpers.GeneralHelper.HandleLibraryOverwrite(formLibraryEntry.Guid, this, command, FormRootPath, customerSchema, LibraryMode.FormLibrary);
try
{
if ((uploadViewModel.UploadData != null) && (uploadViewModel.UploadData.ContentLength > 0) && !string.IsNullOrEmpty(uploadViewModel.UploadData.FileName))
{
var fileName = Path.GetFileName(uploadViewModel.UploadData.FileName);
TemplateLibraryEntry entry = GetTemplateLibraryEntry(designId, customerSchema);
var path = Path.Combine(Server.MapPath("~/"), entry.FilePath, folder.Replace('/', '\\').Trim('\\'), fileName);
uploadViewModel.UploadData.SaveAs(path);
}
else
return Json(new { Message = "Error in saving file, Go back and try again" });
// return RedirectToAction("UploadFile");
//return View(uploadViewModel);
}
catch (Exception)
{
throw;
}
return RedirectToAction("Index");
}
}
But now the json message is shown. The name of the page where you can upload is UploadFile.
I have it now like this:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult UploadFile([Bind(Include = "UploadData,Directories")] /*LibraryUploadModel libraryUpload*/ UploadViewModel uploadViewModel, string designId, string folder, FormLibraryEntry formLibraryEntry, string command)
{
//ActionResultSpecification result = SfsHelpers.GeneralHelper.HandleLibraryOverwrite(formLibraryEntry.Guid, this, command, FormRootPath, customerSchema, LibraryMode.FormLibrary);
try
{
if ((uploadViewModel.UploadData != null) && (uploadViewModel.UploadData.ContentLength > 0) && !string.IsNullOrEmpty(uploadViewModel.UploadData.FileName))
{
var fileName = Path.GetFileName(uploadViewModel.UploadData.FileName);
TemplateLibraryEntry entry = GetTemplateLibraryEntry(designId, customerSchema);
var path = Path.Combine(Server.MapPath("~/"), entry.FilePath, folder.Replace('/', '\\').Trim('\\'), fileName);
uploadViewModel.UploadData.SaveAs(path);
return RedirectToAction("Index");
}
else
{
ModelState.AddModelError("uploadViewModel", "your message");
return View(uploadViewModel);
}
catch (Exception)
{
throw;
}
}
and the view like this:
<div class="col-md-offset-2 col-md-10">
<table>
#for (var i = 0; i < Model.Directories.Count; i++)
{
<tr>
<td>
<fieldset>
<input type="radio" name="folder" value="#Model.Directories[i]" id="folder(#i)">
<label for="folder(#i)">#Model.Directories[i]</label>
</fieldset>
</td>
</tr>
}
</table>
</div>
but the problem is that if you press on Uploaden without an upload file, I get this error:
Line 55: <div class="col-md-offset-2 col-md-10">
Line 56: <table>
Line 57: #for (var i = 0; i < Model.Directories.Count; i++)
Line 58: {
Line 59: <tr>
Source File: b:\Seneca\Producten\FormsServer\Trunk\SenecaFormsServer\Areas\Dashboard\Views\DesignTemplate\UploadFile.cshtml Line: 57
and the directories are null: Model.Directories = null
The problem you have is that you are binding your Directories to your view, but the name attribute of your radio button isn't correctly formed so it won't be posted to the server. Subsequently, when you send the view back with the model that property will be null. Whilst you're at it, use LabelFor as well.
Change it to the following:
#for (var i = 0; i < Model.Directories.Count; i++)
{
<tr>
<td>
<fieldset>
#Html.RadioButtonFor(m => m.Directories, Model.Directories[i])
#Html.LabelFor(m => m.Directories[i])
</fieldset>
</td>
</tr>
}
Related
i have a button in index.html , when press the button will be first to check validation , if You don't have permission, How to display the alert message and redirect to index page in ASP.NET ?
I have try to using return Redirect("Index"); ,but can't show alert message。
please anyone can tell me How to do this?
view/index.html,
<table style="width: 100%;">
<tr>
<td>
<label class="features-title">#ViewBag.Title</label>
#if (rolestr.Contains("Maintain"))
{
#*<p>*#
#Html.ActionLink("Apply", "Create", null, new { #class = "btn btn-primary " })
#*</p>*#
}
</td>
<td class="text-right">
</td>
</tr>
</table>
my controller.cs,
[RoleFilters(Controller = "HA03", Action = "Index", Role = "Maintain")]
public ActionResult Create()
{
StayDormApplication DormApplication = new StayDormApplication();
DormApplication.Sdate = DateTime.Now.AddDays(1);
DormApplication.Edate = DateTime.Now.AddDays(2);
string LoginAccount = Utility.Encryption(User.Identity.Name);
var Member = _db.Members.FirstOrDefault(x => x.Account == LoginAccount);
ViewBag.Name = Utility.Decryption(Member.Name);
ViewBag.AppType = Member.TradeName;
DateTime now = DateTime.Now;
var RoomInfo = _db.DormApplications.Where(p => p.Poster == username && now > p.Sdate && now <p.Edate).FirstOrDefault();
if (RoomInfo == null)
{
Response.Write("<script>alert('You don't have permission to access /register.'); </script>");
return Redirect("Index");
}
return View(DormApplication);
}
at this moment I am uploading any file and saving it. What I want is to generate an error message if the user does not select any file and press the upload button, but at this moment the only thing it does is redirect to another view whether or not it has selected files. I would like to know if there is another better way to generate the upload of these files
this is my controller
public class HomeController : Controller
{
// GET: Home
public ActionResult Index()
{
return View();
}
[HttpPost]
public void Upload(HttpPostedFileBase file)
{
string file = (file.FileName).ToLower();
try
{
file.SaveAs(Server.MapPath("~/Uploads/" + file));
}
catch (Exception e)
{
ViewBag.UploadError = "Upload file error";
}
}
}
this is the view:
#{
ViewBag.Title = "Home";
}
#using (Html.BeginForm("Transformation", "Xml", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div class="col-md-12 offset-md-5">
<div class="custom-file col col-lg-2">
<input type="file" name="file" class="custom-file-input" id="inputGroupFile01" aria-describedby="inputGroupFileAddon01">
<label class="custom-file-label" for="inputGroupFile01">Choose file</label>
</div>
<div class="col-5">
<button class="btn btn-success col-md-4 mt-2" type="submit">Upload file</button>
</div>
</div>
//Message Error
<div class="alert alert-danger" role="alert">
<p class="text-danger">
#ViewBag.UploadError
</p>
</div>
}
#Thomas Caycedo Martinez, I believe you can simply modify your controller method like below.
If error, return to the same view with an error message.
Your view remains unchanged.
[HttpPost]
public ActionResult Upload(HttpPostedFileBase file)
{
if (file != null)
{
string fileName = (file.FileName).ToLower();
try
{
file.SaveAs(Server.MapPath("~/Uploads/" + fileName));
}
catch (Exception e)
{
ViewBag.UploadError = "Upload file error";
return View("Index");
}
}
else {
ViewBag.UploadError = "Upload file error";
return View("Index");
}
return View();
}
write the action and controller correctly
#using (Html.BeginForm("Upload", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
and check file in action
[HttpPost]
public ActionResult Upload(HttpPostedFileBase file)
{
if( file != null && file.Length > 0)
{
string file = (file.FileName).ToLower();
try
{
file.SaveAs(Server.MapPath("~/Uploads/" + file));
}
catch (Exception e)
{
ViewBag.UploadError = "Upload file error";
}
return View("Index");
}
else
{
//do something
return View("Index");
}
}
You can use JavaScript/JQuery to check for the same..
$(function(){
$("#btnSubmit").on("click",function(){
if($("#inputGroupFile01").val()==""){
alert("Please select a file")
return false;
}
})
})
where btnSubmit is the id for the submit button
am having a weird functionality when am only updating other fields other than the image , the other fields (FirstName , LastName) update successfully but then the Image sets its self to null, but when I choose it with respect to other fields (FirstName, LastName) it updates successfully. So what I want is when I don't update the image it stays as it is without setting its self to null.
This is my New.cshtm file which handles both Creating and Editing data :
<form asp-action="New" method="Post" asp-controller="Student" enctype="multipart/form-data">
<div asp-validation-summary="All"></div>
<input asp-for="Id" type="hidden"/>
<input name="IsEditMode" id="IsEditMode" value="#ViewBag.IsEditMode" type="hidden"/>
<div class="form-row">
<label>Upload Photo</label>
<input asp-for="ImageUrl" type="file" id="file" name="file" class="form-control"/>
</div>
<div class="form-row">
<div class="col">
<label asp-for="FirstName"></label>
<input asp-for="FirstName" class="form-control"/>
<span asp-validation-for="FirstName" class="text-danger"></span>
</div>
<div class="col">
<label asp-for="MiddleName"></label>
<input asp-for="MiddleName" class="form-control"/>
<span asp-validation-for="MiddleName" class="text-danger"></span>
</div>
</div>
</form>
Then these are the methods of my controller Student.cs am using to update the fields :
public IActionResult New(Student student, string IsEditMode, IFormFile file)
{
if (!ModelState.IsValid)
{
ViewBag.IsEditMode = IsEditMode;
return View(student);
}
try
{
if (IsEditMode.Equals("false"))
{
_studentRepository.Create(student);
UploadFile(file, student.Id);
_toastNotification.AddSuccessToastMessage("Student has been created successfully.");
}
else
{
_studentRepository.Edit(student);
UploadFile(file, student.Id);
_toastNotification.AddSuccessToastMessage("Student has been edited successfully.");
}
return RedirectToAction(nameof(Index));
}
catch (Exception e)
{
return RedirectToAction(nameof(Index));
}
}
public IActionResult Edit(int id)
{
try
{
ViewBag.IsEditMode = "true";
var student = _studentRepository.GetSingleStudent(id);
return View("New", student);
}
catch (Exception ex)
{
return Content("Could not find Pet");
}
}
public void UploadFile(IFormFile file, long studentId)
{
var fileName = file.FileName;
var path = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/images",fileName);
using (var fileStream = new FileStream(path, FileMode.Create))
{
file.CopyTo(fileStream);
}
var student = _studentRepository.GetSingleStudent(studentId);
student.ImageUrl = fileName;
_studentRepository.Edit(student);
}
Then, this is how I am Updating in the Repository :
Then in my Repository, this is how I am updating the fields " :
public void Edit(Student student)
{
var existingStudent = _context.Students
.FirstOrDefault(s => s.Id == student.Id);
if (existingStudent != null)
{
// updating student.
_context.Entry(existingStudent).CurrentValues.SetValues(student);
_context.Entry(existingStudent).State = EntityState.Modified;
}
}
The Index.cshtml, this is one list the images and the First and LastName and the (action buttons) Edit, Delete buttons :
<table class="table table-striped">
<thead class="thead-dark">
<tr>
<td ><b>Student Picture</b></td>
<td><b>FirstName</b></td>
<td><b>LastName</b></td>
<td colspan="2"> <b>Actions</b></td>
</tr>
</thead>
<tbody>
#foreach (var student in Model)
{
<tr>
<td>#student.StudentRegNo</td>
<td>
<div class="thumbnail">
<img src="/images/#student.ImageUrl" width="90" height="90"/>
</div>
</td>
<td>#student.FirstName</td>
<td>#student.LastName</td>
<d>
<td>
<a class="btn btn-warning" asp-action="Details" asp-controller="Student" asp-route-Id="#student.Id">Details</a>
</td>
<td>
<a class="btn btn-primary" asp-action="edit" asp-route-Id="#student.Id">Edit</a>
</td>
<td>
<a
class="btn btn-danger delete"
asp-route-Id="#student.Id"
asp-action="Delete">
Delete
</a>
</td>
</d>
</tr>
}
</tbody>
</table>
EDIT
This is the current logic am having according to #Raul solution, but it's not working :
if (student.ImageUrl != null)
{
_context.Entry(existingStudent).CurrentValues.SetValues(student);
_context.Entry(existingStudent).State = EntityState.Modified;
}
else
{
_context.Entry(existingStudent).Property(x => x.ImageUrl).IsModified = false;
_context.Entry(existingStudent).CurrentValues.SetValues(student);
_context.Entry(existingStudent).State = EntityState.Modified;
}
You could consider the two scenario separately.When updating fields without updating the image, the file is null, then you need to assgin the ImageUrl of existing student to the posted student.
//...
try
{
if (IsEditMode.Equals("false"))
{
_studentRepository.Create(student);
UploadFile(file, student.Id);
_toastNotification.AddSuccessToastMessage("Student has been created successfully.");
}
else
{
//edit mode
if(file == null)//Updating fields without updating the image.
{
var existingStudent = _context.Students.FirstOrDefault(s => s.Id == student.Id);
if (existingStudent != null)
{
// updating student with previousImageUrl
student.ImageUrl = existingStudent.ImageUrl;
_context.Entry(existingStudent).CurrentValues.SetValues(student);
_context.Entry(existingStudent).State = EntityState.Modified;
_context.SaveChanges();
}
}
else//Updating the fields and the image
{
_studentRepository.Edit(student);
UploadFile(file, student.Id);
}
_toastNotification.AddSuccessToastMessage("Student has been edited successfully.");
}
return RedirectToAction(nameof(Index));
}
catch (Exception e)
{
return RedirectToAction(nameof(Index));
}
}
public void UploadFile(IFormFile file, long studentId)
{
var fileName = file.FileName;
var path = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/images", fileName);
using (var fileStream = new FileStream(path, FileMode.Create))
{
file.CopyTo(fileStream);
}
var student = _studentRepository.GetSingleStudent(studentId);
student.ImageUrl = fileName;
_studentRepository.Edit(student);
}
public void Edit(Student student)
{
var existingStudent = _context.Students
.FirstOrDefault(s => s.Id == student.Id);
if (existingStudent != null)
{
// updating student.
_context.Entry(existingStudent).CurrentValues.SetValues(student);
_context.Entry(existingStudent).State = EntityState.Modified;
_context.SaveChanges();
}
}
In your Edit student method, you can set the IsModified to false for your ImageUrl Property which will not update the image field in your database:
public void Edit(Student student)
{
var existingStudent = _context.Students.FirstOrDefault(s => s.Id == student.Id);
if (existingStudent != null)
{
// updating student.
_context.Student.Attach(existingStudent);
_context.Entry(existingStudent).State = EntityState.Modified;
_context.Entry(existingStudent).Property(x => x.ImageUrl).IsModified=false;
_context.SaveChanges();
}
}
Of course, you would need to check for your ImageUrl logic in this. If you get a new image then you update your model accordingly.
EDIT:
You can incorporate your if-else condidition like this:
if (student.ImageUrl != null)
{
_context.Student.Add(existingStudent);
_context.Entry(existingStudent).State EntityState.Modified;
//_context.Student.Update(existingStudent); //You can also use this. Comment out the upper two lines
_context.SaveChanges();
}
else
{
// updating student.
_context.Student.Attach(existingStudent);
_context.Entry(existingStudent).State = EntityState.Modified;
_context.Entry(existingStudent).Property(x => x.ImageUrl).IsModified=false;
_context.SaveChanges();
}
I use asp.net core razor pages to create my application, in my create page, I have two file controls, one for upload icon image and the other for uploading detail images. But when I click edit button, all of the fields were initialized, except the two file controls. Please check my code. Anyone can help?
In my razor page:
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label asp-for="Product.Icon" class="control-label"></label>
<input asp-for="#Model.Icon" type="file" />
<span asp-validation-for="Product.Icon" class="text-danger"></span>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label class="control-label”>Detail Images(support multi-uploading):</label>
<input type="file" id="fUpload" name="files" multiple />
</div>
</div>
</div>
In my page model:
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}
Product = await _context.Products
.Include(p => p.Shop).SingleOrDefaultAsync(m => m.ID == id);
if (Product == null)
{
return NotFound();
}
ViewData["Shop"] = new SelectList(_context.Shops, "ID", "Name");
return Page();
}
public async Task<IActionResult> OnPostAsync(List<IFormFile> files)
{
if (!ModelState.IsValid)
{
return Page();
}
var uploads = Path.Combine(hostingEnvironment.WebRootPath, "uploads");
if (!Directory.Exists(uploads))
{
Directory.CreateDirectory(uploads);
}
if (this.Icon != null)
{
var fileName = GetUniqueName(this.Icon.FileName);
var filePath = Path.Combine(uploads, fileName);
this.Icon.CopyTo(new FileStream(filePath, FileMode.Create));
this.Product.Icon = fileName;
}
if (files != null && files.Count > 0)
{
foreach (IFormFile item in files)
{
if (item.Length > 0)
{
var fn = GetUniqueName(item.FileName);
var fp = Path.Combine(uploads, fn);
item.CopyTo(new FileStream(fp, FileMode.Create));
this.Product.ProductImages = this.Product.ProductImages + fn + "^";
}
}
}
_context.Attach(Product).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!ProductExists(Product.ID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToPage("./Index");
}
The most important part of your page is missing from the code you provided - the <form> tag. For file uploading to work, you must specify that the method is post and you must also provide an enctype attribute with its value set to multipart/form-data:
<form method="post" enctype="multipart/form-data">
...
Ref: https://www.learnrazorpages.com/razor-pages/forms/file-upload
I am attempting to upload a file. The code below works on my local machine or running on a remote server running the dll from a command line, but when I try and publish to my test environment and run under iis it fails.
<form method="post" asp-action="Upload" asp-controller="Prebook" enctype="multipart/form-data">
<div class="form-inline">
<div class="col-md-2">
<div class="form-group">
<input type="file" name="files" data-input= "false" multiple class="filestyle" data-buttonName="btn-primary">
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<input type="submit" value="Upload File" class="btn btn-primary" />
</div>
</div>
</div>
</form>
Controller logic
[HttpPost]
public async Task<IActionResult> Upload(ICollection<IFormFile> files)
{
if (await _contextPB.UploadRow.AnyAsync())
{
Danger(string.Format("Please LOAD the existing containers before uploading another file"), true);
return View();
}
int rowCount = 0;
var uploads = Path.Combine(_environment.WebRootPath, "uploads");
var _viewModel = new UploadViewModel();
foreach (var file in files)
{
using (var streamReader = System.IO.File.OpenText(Path.Combine(uploads, file.FileName)))
{
var line = streamReader.ReadLine();
var columnNames = line.Split(new[] { ',' });
if (!ValidateColumnNames(columnNames))
{
Danger(string.Format("Invalid Column Name in Upload file"), true);
return View(_viewModel);
}
while (!streamReader.EndOfStream)
{
var data = line.Split(new[] { ',' });
var uploadRow = new UploadRow();
// validation & assignment logic removed
try
{
_contextPB.Add(uploadRow);
rowCount++;
}
catch (Exception e)
{
Danger(string.Format("<b>{0},{1}</b> database error", uploadRow.Container_Id, e), true);
}
line = streamReader.ReadLine();
}
}
}
}
Try adding a catch block to see what the error is.
I'm assuming a permission issue.
[HttpPost]
public async Task<IActionResult> Upload(ICollection<IFormFile> files)
{
try
{
if (await _contextPB.UploadRow.AnyAsync())
{
Danger(string.Format("Please LOAD the existing containers before uploading another file"), true);
return View();
}
// your code
}
catch (Exception ex)
{
// what is the error?
// add a breakpoint to see
throw;
}
}