How to delete uploaded files from specific user - javascript

i'm using this http://www.dropzonejs.com/ in my create form
When user click "Click here to add files" the files are stored in Files/TempFile
but when user click submit on my create method i want to move all files from Files/TempFile to Files/TicketFile uploaded from the user, or if user click cancel to delete all files from Files/TempFile.
The problem is what if there are several user that trying to upload files in the same time. If one of the user click cancel or submit how to know which files to move or delete.
CREATE VIEW
#{
ViewBag.Title = "Create";
}
#using (Html.BeginForm("Create", "Ticket", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>Ticket</legend>
<div class="editor-label">
#Html.LabelFor(model => model.idTicket)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.idTicket)
#Html.ValidationMessageFor(model => model.idTicket)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.idProject, "Project")
</div>
<div class="editor-field">
#Html.DropDownList("idProject", String.Empty)
#Html.ValidationMessageFor(model => model.idProject)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.tickettDescription)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.tickettDescription)
#Html.ValidationMessageFor(model => model.tickettDescription)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.assignment, "User")
</div>
<div class="editor-field">
#Html.DropDownList("assignment")
#Html.ValidationMessageFor(model => model.assignment)
</div>
<div class="jumbotron">
<div class="dropzone" id="dropzoneForm" style="width: 50px; background: none; border: none;">
<div class="fallback">
<input type="file" id="fileInput" name="files" multiple="multiple" >
<input type="submit" id="submit" value="Upload" />
</div>
</div>
</div>
<div class="clear-fix"></div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
<script type="text/javascript">
//File Upload response from the server
Dropzone.options.dropzoneForm = {
init: function () {
this.on("maxfilesexceeded", function (data) {
$.ajax({
url: '#Url.Action("SaveUploadedFile", "File", new { id=1})',
})
var res = eval('(' + data.xhr.responseText + ')');
});
this.on("addedfile", function (file) {
// Create the remove button
var removeButton = Dropzone.createElement("<button>Remove file</button>");
// Capture the Dropzone instance as closure.
var _this = this;
// Listen to the click event
removeButton.addEventListener("click", function (e) {
// Make sure the button click doesn't submit the form:
e.preventDefault();
e.stopPropagation();
// Remove the file preview.
$.ajax({
type: "POST",
url: '#Url.Action("RemoveFile","File")',
contentType: "application/json; charset=utf-8",
data: "{name:" + JSON.stringify(file.name) + "}",
dataType: "json",
success: function () { _this.removeFile(file); }
});
})
// Add the button to the file preview element.
file.previewElement.appendChild(removeButton);
});
}
};
</script>
Save Method
public ActionResult SaveUploadedFile()
{
bool isSavedSuccessfully = true;
string fName = "";
try
{
foreach (string fileName in Request.Files)
{
HttpPostedFileBase file = Request.Files[fileName];
//Save file content goes here
fName = file.FileName;
if (file != null && file.ContentLength > 0)
{
string path = Server.MapPath("~/Files/TempFile/") + file.FileName;
file.SaveAs(path);
}
}
}
catch (Exception ex)
{
isSavedSuccessfully = false;
}
if (isSavedSuccessfully)
{
return Json(new { Message = fName });
}
else
{
return Json(new { Message = "Error in saving file" });
}
}
i tried not to store to TempFile and when i click create to get all the files with
foreach (string fileName in Request.Files)
but Request.Files is always null.

While uploading your file to Files/TempFile add dummmy suffix to it to identify the user who is uploading the file eg. if user say "ABC" is uploading file "File1" then in your code for uploading file rename file as "File1_ABC". Similarly if user "PQR" is uploading "File1" then uploaded file in the folder should be "File1_PQR" now when user "ABC" click submit on your create method move file from Files/TempFile to Files/TicketFile having suffix as "_ABC".

Related

ASP.Net MVC File Upload via Bootstrap Modal Dialog results redirect browser

I'm having a basic form with few text fields and a file upload controller on a bootstrap modal dialog (Bootstrap 4). below is my code:
Model:
public class DemoContent
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
[RegularExpression("([0-9]+)",ErrorMessage = "Age must be numbers only")]
public int Age { get; set; }
[EmailAddress]
public string Email { get; set; }
[DataType(DataType.Upload)]
[Display(Name = "Image")]
public HttpPostedFileBase ImageUrl { get; set; }
}
JavaScript
$(function() {
$("a[data-modal=demoPopup]").on("click", function () {
$("#demoModalContent").load(this.href, function () {
$("#demoModal").modal({ keyboard: true }, "show");
$("#demoForm").submit(function () {
if ($("#demoForm").valid()) {
var files = $("ImageUrl").get(0).files;
var data = $(this).serialize();
data.append("ImageUrl", files[0]);
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
success: function (result) {
if (result.success) {
$("#demoModal").modal("hide");
location.reload();
} else {
$("#MessageToClient").text(result.message);
}
},
error: function () {
$("#MessageToClient").text("The web server had an error.");
}
});
return false;
}
});
});
return false;
});
Controller:
[HttpPost]
public ActionResult Create(DemoContent model)
{
if (model.Age > 55)
{
var file = model.ImageUrl;
return Json(new { success = true });
}
else
{
return Json(new { success = false,message="Invalid Data" });
}
}
Now when i open the popup it works also when i submit the form it goes to the controller along with the file. but the problem is once the server returns the success message the popup shows that message in a blank page instead of capturing it and refreshing the current page or showing the messages. any idea why is this happening.
link to source files : https://drive.google.com/open?id=1W3H3kFEpHJWfaf7_UnJI3O5I900GxyC7
May be you wrote your javascripts function in document.ready() function,That is why it again refreshing.
Write your JavaScript code as follows:
$(function() {
$("a[data-modal=demoPopup]").on("click", function () {
$("#demoModalContent").load(this.href, function () {
$("#demoModal").modal({ keyboard: true }, "show");
$("#demoForm").submit(function (event) { // Pass the event as parameter to the function.
event.preventDefault(); // I have added these two lines
event.stopImmediatePropagation();
if ($("#demoForm").valid()) {
var files = $("ImageUrl").get(0).files;
var data = $(this).serialize();
data.append("ImageUrl", files[0]);
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
success: function (result) {
if (result.success) {
$("#demoModal").modal("hide");
location.reload();
} else {
$("#MessageToClient").text(result.message);
}
},
error: function () {
$("#MessageToClient").text("The web server had an error.");
}
});
return false;
}
});
});
return false;
});
I think you should install and use Microsoft.Unobtrusive.Validation and *.Ajax, if you want your modal to be updated (I get your question like that...). With this, you can use code like the following example, which can update your modal (used this in a project a few days ago):
Modal:
#using (Ajax.BeginForm("Login", new { Controller = "Home", area = "" }, new AjaxOptions() { OnSuccess = "onSuccessLogin", HttpMethod = "POST", UpdateTargetId = "loginmodalbody"}, new { id = "loginForm" }))
{
<div class="modal-body" id="loginmodalbody">
<div class="text-danger loginfailed"></div>
<div class="container">
<div class="card border-primary mb-3" style="margin: 0 auto;">
<div class="card-body">
#Html.Partial("~/Views/Shared/Modals/LoginModalBody.cshtml")
</div>
</div>
<div class="container">
<span><a onclick="alert('Leads to pw info')" href="#">Forgot password?</a></span>
</div>
<br />
<button class="btn btn-primary btn-block buttonlogin">Login</button>
</div>
<br />
</div>
}
Modal Body:
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
<div class="col-lg-12 col-12">
#Html.EditorFor(model => model.EMail, new { htmlAttributes = new { #class = "form-control", placeholder = "EMail", #id = "inputemail" } })
#Html.ValidationMessageFor(model => model.EMail, "", new { #class = "text-danger", #id = "dangeremail" })
</div>
</div>
<div class="form-group">
<div class="col-lg-12 col-12">
#Html.EditorFor(model => model.Password, new { htmlAttributes = new { #class = "form-control", placeholder = "Passwort", #id = "inputpassword" } })
#Html.ValidationMessageFor(model => model.Password, "", new { #class = "text-danger", #id = "dangerpassword" })
</div>
</div>
</div>
Thus, it updates your modal body after getting data from the posting of the form - you define the id to be updated within the AjaxOptions, as shown in the above snippet.

Redirect to action with JsonResult in MVC

I have a Room record in my database and I want to edit it using a JsonResult Edit method in RoomController like this:
[HttpPost]
[ValidateAntiForgeryToken]
public JsonResult Edit(RoomViewModel roomViewModel)
{
if (roomViewModel == null) throw new ArgumentNullException(nameof(roomViewModel));
try
{
var apartmentRoomViewModel = new ApartmentRoomViewModel
{
Id = _entities.ApartmentRoom.Where(x => x.RoomID == roomViewModel.Id).Select(x => x.Id).Single(),
ApartmentID = _entities.ApartmentRoom.Where(x => x.RoomID == roomViewModel.Id).Select(x => x.ApartmentID).Single(),
RoomID = roomViewModel.Id
};
apartmentRoomViewModel.ApartmentID = roomViewModel.SelectedApartmentID;
var apartmentRoom = AutoMapper.Mapper.Map<ApartmentRoom>(apartmentRoomViewModel);
_entities.ApartmentRoom.AddOrUpdate(apartmentRoom);
_entities.SaveChanges();
var room = AutoMapper.Mapper.Map<Room>(roomViewModel);
var status = _roomRepository.Update(room);
_roomRepository.Save();
return Json(new { status, message = "Success!", url = Url.Action("List", "Room") });
}
catch
{
return Json(new { status = false, message = "Error!" });
}
}
After the method works, edit is successful but I cannot redirect the page to /Room/List. Instead, I am encountering a page like this:
My Script
<script type="text/javascript">
$(document).ready(function () {
$("#RoomEdit").click(function (e) {
e.preventDefault();
var data = {
DoorNumber: $("#DoorNumber").val(),
FloorNumber: $("#FloorNumber").val(),
Capacity: $("#Capacity").val(),
SelectedApartmentID: $("#SelectedApartmentID option:selected").val()
}
$.ajax({
type: "POST",
url: '#Url.Action("Edit","Room")',
dataType: "json",
data: JSON.stringify(data),
contentType: "application/json",
success: function (result) {
if (result.status) {
window.location.href = result.url;
}
},
error: function () {
}
});
return false;
});
});
Edit.cshtml
<div class="row">
<div class="col-md-10 offset-md-1">
<div class="box">
<div class="box-header">
<h2>#ViewBag.Title</h2>
</div>
<div class="box-divider m-a-0"></div>
<div class="box-body">
#using (Html.BeginForm("Edit", "Room", FormMethod.Post))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group row">
#Html.LabelFor(x => x.DoorNumber, new { #class = "col-sm-2 form-control-label" })
<div class="col-sm-10">
#Html.TextBoxFor(x => x.DoorNumber, new { #class = "form-control" })
#Html.ValidationMessageFor(x => x.DoorNumber, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group row">
#Html.LabelFor(x => x.FloorNumber, new { #class = "col-sm-2 form-control-label" })
<div class="col-sm-10">
#Html.TextBoxFor(x => x.FloorNumber, new { #class = "form-control" })
#Html.ValidationMessageFor(x => x.FloorNumber, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group row">
#Html.LabelFor(x => x.Capacity, new { #class = "col-sm-2 form-control-label" })
<div class="col-sm-10">
#Html.TextBoxFor(x => x.Capacity, new { #class = "form-control" })
#Html.ValidationMessageFor(x => x.Capacity, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group row">
#Html.LabelFor(x => x.ApartmentName, new { #class = "col-sm-2 form-control-label" })
<div class="col-sm-10">
#Html.DropDownListFor(x => x.SelectedApartmentID, Model.ApartmentList, new { #class = "form-control", id = "SelectedApartmentID" })
</div>
</div>
<div class="form-group row m-t-md">
<div class="col-sm-offset-2 col-sm-10">
<button type="button" id="RoomEdit" class="btn green">Düzenle</button>
</div>
</div>
}
</div>
</div>
</div>
I couldn't understand what is wrong with my code. Any help will be appreciated.
Make your Button first with type="Button" instead of Submit, also change the click function id from btnAdd to btnEdit.
At server side, roomViewModel.Id will be getting 0 if you using old method, instead of this do serialize so you can get all the Inputs at server side method.
Also use, #Html.HiddenFor(x => x.id) to pass the Id to Method.
Try this function so you can call your Method with AJAX,
<script type="text/javascript">
$(document).ready(function () {
$("#RoomEdit").click(function (e) {
e.preventDefault();
var data = $("#formName").serialize();
$.ajax({
type: "POST",
url: '#Url.Action("Edit", "Room")',
data: data,
success: function (result) {
if (result.status) {
alert(result.message);
setTimeout(function () {
window.location.href = result.url;
}, 1000);
}
}
});
});
})
</script>
You have code to do ajax submit. But from the image you shared, it looks like it is doing a normal form submit. Make sure that you are preventing the default form submit behavior when the button is clicked.
You already have return false; which should do it.
It should work as long as you do not have other script errors in the page. (you can verify this by opening up the browser console)
Also make sure that you are returning true as the value of status property of the json data you are returning. There is no need to specify JsonRequestBehavior.AllowGet enum in the Json method overload when you are returning from an HttpPost action method. It is needed if your action method is HttpGet
return Json(new { status= true, message = "Success!", url = Url.Action("List", "Room") });
Also, it does not make any sense to have the $.notify call after you redirect to the new page. That means that call will not be executed at all!

MVC dynamic validation in bootstrap modal not blocking submit

I've a dynamic form (bootstrap modal) where I want to use data validation.
Therefor when the modal is being shown I apply the validator in my a script.
This is my jquery/javascript code in the index page for showing the modal
$("#btnCreate").on("click", function (e) {
// hide dropdown if any
$(e.target).closest('.btn-group').children('.dropdown-toggle').dropdown('toggle');
$('#myModalContent').load(this.href, function () {
$('#myModal').modal({
/*backdrop: 'static',*/
keyboard: true
}, 'show');
$('#myModal').on('shown.bs.modal', function () {
$('.chzn-select', this).chosen({ width: "inherit", disable_search: true });
/*$("form").data("validator", null);
$.validator.unobtrusive.parse($("form"));*/
var form = $("form") //use more specific selector if you like
form.removeData("validator").removeData("unobtrusiveValidation");
$.validator.unobtrusive.parse(form);
});
bindForm(this);
});
return false;
});
function bindForm(dialog) {
$('form', dialog).submit(function () {
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
success: function (result) {
if (result.success) {
$('#myModal').modal('hide');
//Refresh
location.reload();
} else {
$('#myModalContent').html(result);
bindForm();
}
}
});
return false;
});
The validation works, but the problem is as follows:
So when I click on the submit button, without the required fields filled in the form still submits. Instead of blocking the POST and telling the user something is wrong.
This is my create view:
#using (Html.BeginForm("Create", "Home", FormMethod.Post, new { #class="horizontal-form"})) {
#Html.ValidationSummary(false)
<div class="modal-body">
<fieldset>
<div class="form-group">
<div class="editor-label">
#Html.LabelFor(model => model.Naam)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.Naam, new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.Naam)
</div>
</div>
<div class="form-group">
<div class="editor-label">
#Html.LabelFor(model => model.Omschrijving)
</div>
<div class="editor-field">
#Html.TextAreaFor(model => model.Omschrijving, new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.Omschrijving, "", new { #class = "text-danger" })
</div>
</div>
<div class="modal-footer">
<input type="submit" id="verstuurFormulier" value="Create" class="btn btn-primary" />
</div>
</fieldset>
</div>
}
You're not stopping the normal submit from happening:
function bindForm(dialog) {
$('form', dialog).submit(function (e) {
e.preventDefault();
$.ajax({
...
This means that you have to manually decide when to submit though. I use the following in some of my projects:
$('#myForm').removeData("validator");
$.validator.unobtrusive.parse($('#myForm'));
if ($('#myForm').valid()) {
$('#myForm').submit();
}
return false;
I think the problem might lie in the line:
$("form").data("validator", null);
I usually use this little snippet (found ofc on StackOverflow, but I do not remember the person to give credit to :( )
(function ($) {
$.validator.unobtrusive.parseDynamicContent = function (selector) {
//use the normal unobstrusive.parse method
$.validator.unobtrusive.parse(selector);
//get the relevant form
var form = $(selector).first().closest('form');
//get the collections of unobstrusive validators, and jquery validators
//and compare the two
var unobtrusiveValidation = form.data('unobtrusiveValidation');
var validator = form.validate();
$.each(unobtrusiveValidation.options.rules, function (elname, elrules) {
if (validator.settings.rules[elname] == undefined) {
var args = {};
$.extend(args, elrules);
args.messages = unobtrusiveValidation.options.messages[elname];
//edit:use quoted strings for the name selector
$("[name='" + elname + "']").rules("add", args);
} else {
$.each(elrules, function (rulename, data) {
if (validator.settings.rules[elname][rulename] == undefined) {
var args = {};
args[rulename] = data;
args.messages = unobtrusiveValidation.options.messages[elname][rulename];
//edit:use quoted strings for the name selector
$("[name='" + elname + "']").rules("add", args);
}
});
}
});
}
})($);
Then just delete the null on form validator and change the parse call to:
$.validator.unobtrusive.parseDynamicContent('form');
Hope this helps.

MVC: Submit on TextBox change

I have a textbox on my MVC 4 view, and I would like to let the user press Enter on changing the text and call a controller's action method. Thanks.
Here is a part of my view:
#using (Html.BeginForm())
{
<div class="editor">
#Html.LabelFor(m => m.FolderPath)
#Html.TextBoxFor(m => m.FolderPath, new { #Id = "FolderPath", #style="width:500px;" })
#Html.ValidationMessageFor(m => m.FolderPath)
</div>
And a part of the controller:
[HttpPost]
[MultipleButton(Name = "action", Argument = "Refresh")]
public ActionResult Refresh(EdiFileModel ediFileModel)
{
if (Directory.Exists(ediFileModel.FolderPath))
{
FolderPath = ediFileModel.FolderPath;
}
else
{
ModelState.AddModelError("FolderPath", "This folder does not exist!");
}
ediFileModel = Load();
return View("Index", ediFileModel);
}
Add a submit button...
<input type="submit" value="Submit"/>
inside your form.

how to configure custom upload area in dropzone.js with mvc4 form

I just started looking into dropzone.js Is it possible to somehow modify the previewTemplate area to add additional info about the files uploaded and then submit the form to an mvc method?
For simplicity I want to add two fields DocumentTypeID and ExpirationDate for each file that a user wants to upload
#model MyProject.Model.Document
#using (Html.BeginForm("Create", "Document", FormMethod.Post, new { enctype = "multipart/form-data", #class = "dropzone", #id = "my-awesome-dropzone" }))
{
<div class="row-fluid">
<fieldset class="span6">
<div class="editor-label">
#Html.LabelFor(model => model.DocumentTypeID, "DocumentType")
</div>
<div class="editor-field">
#Html.DropDownList("DocumentTypeID", String.Empty)
#Html.ValidationMessageFor(model => model.DocumentTypeID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ExpirationDate)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ExpirationDate)
#Html.ValidationMessageFor(model => model.ExpirationDate)
</div>
</fieldset>
<div class="span6"> <div class="dropzone-previews"></div> </div>
</div>
}
Here is the controller method which for now should accept one file at a time
[HttpPost]
public ActionResult Create(Document document, HttpPostedFileBase file)
{
if (ModelState.IsValid && file != null)
{
db.Documents.Add(document);
document.FilePath = ProcessDocumentUpload(Request.Files[0], document.DocumentID);
db.SaveChanges();
return "";//? // not sure what to return yet
}
}
Now the Js function for dropzone
<script type="text/javascript">
$(function () {
// "myAwesomeDropzone" is the camelized version of the HTML element's ID
Dropzone.options.myAwesomeDropzone = {
autoDiscover: false,
paramName: "file", // The name that will be used to transfer the file
maxFilesize: 5, // MB
maxFiles: 1, //for now upload one at a time
//I started looking at the template and added two elements as an experiment.
previewTemplate: "<div class=\"dz-preview dz-file-preview\">\n <div class=\"dz-details\">\n <div class=\"dz-filename\"><span data-dz-name></span></div>\n <div class=\"dz-size\" data-dz-size></div>\n <img data-dz-thumbnail />\n </div>\n <input type=\"text\" data-dz-doc-expiration-date class=\"dz-doc-input\" />\n <select class=\"dz-doc-input\" data-dz-doc-document-type-id ></select>\n <div class=\"dz-progress\"><span class=\"dz-upload\" data-dz-uploadprogress></span></div>\n <div class=\"dz-success-mark\"><span>✔</span></div>\n <div class=\"dz-error-mark\"><span>✘</span></div>\n <div class=\"dz-error-message\"><span data-dz-errormessage></span></div>\n</div>",
//dictDefaultMessage: "Drop files here to upload or click",
// The configuration that allows the whole form to be submitted on button click
autoProcessQueue: false,
uploadMultiple: false,
parallelUploads: 1,
addRemoveLinks: true,
previewsContainer: ".dropzone-previews", //show a preview in another place
// The setting up of the dropzone
init: function () {
var myDropzone = this;
// First change the button to actually tell Dropzone to process the queue.
$("input[type=submit]").on("click", function (e) {
// Make sure that the form isn't actually being sent.
e.preventDefault();
e.stopPropagation();
myDropzone.processQueue();
});
// Listen to the sendingmultiple event. In this case, it's the sendingmultiple event instead
// of the sending event because uploadMultiple is set to true.
this.on("sendingmultiple", function () {
// Gets triggered when the form is actually being sent.
// Hide the success button or the complete form.
});
this.on("successmultiple", function (files, response) {
// Gets triggered when the files have successfully been sent.
// Redirect user or notify of success.
});
this.on("errormultiple", function (files, response) {
// Gets triggered when there was an error sending the files.
// Maybe show form again, and notify user of error
});
},
accept: function (file, done) {
//maybe do something here for showing a dialog or adding the fields to the preview?
}
};
});
</script>
Thanks for looking!
have you tried to handle the event 'sending'?
$dropzone.on('sending', function (file, xhr, formData) {
formData.append('id', $id);
});
MVC controller
public JsonResult UploadImage(string id)
{
for (int i = 0; i < Request.Files.Count; i++)
{
HttpPostedFileBase file = Request.Files[i];
...
}
return Json(true, JsonRequestBehavior.DenyGet);
}
I've been using also MVC 4 and it has worked well.

Categories

Resources