Ajax FileUpload & JQuery formData in ASP.NET MVC - c#

I have some problem with posting formData to server side action method. Because ajax call doesn't send files to server, I have to add file uploader data to formData manually like this:
var formData = new FormData();
formData.append("imageFile", $("#imageFile").file);
formData.append("coverFile", $("#coverFile").file);
I wrote jQuery function that need to post form data to server using ajax call.
It's works but posted formData in server side is always null!
this is my script:
<script>
function SubmitButtonOnclick()
{
var formData = new FormData();
formData.append("imageFile", $("#imageFile").file);
formData.append("coverFile", $("#coverFile").file);
$.ajax({
type: "POST",
url: '#Url.Action("EditProfile", "Profile")',
data: formData,
dataType: 'json',
contentType: "multipart/form-data",
processData: false,
success: function (response) {
$('#GeneralSection').html(response.responseText);
},
error: function (error) {
$('#GeneralSection').html(error.responseText);
}
});
}
</script>
Edit 1:
This is the action method in controller:
public ActionResult EditProfile(ProfileGeneralDescription editedModel,
HttpPostedFileBase imageFile,
HttpPostedFileBase coverFile,
string postOwnerUser)
{
try
{
if (postOwnerUser == User.Identity.Name)
{
// edit codes...
var result = GetProfileGeneralDescription(postOwnerUser);
return PartialView("_GeneralProfile", result);
}
else
{
var error = new HandleErrorInfo(
new Exception("Access Denied!"),
"Profile",
EditProfile
return PartialView("~/Views/Shared/Error.cshtml", error);
}
}
catch (Exception ex)
{
var error = new HandleErrorInfo(ex, "Profile", EditProfile
return PartialView("~/Views/Shared/Error.cshtml", error);
}
}
Edit 2:
Cshtml view file content:
#model Website.Models.ViewModel.Profile
#using (Ajax.BeginForm("EditProfile", "Profile", new { postOwnerUser = User.Identity.Name }, new AjaxOptions()
{
HttpMethod = "POST",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "GeneralSection"
}, new { enctype = "multipart/form-data" }))
{
<div>
<button id="btnSubmit" type="button" onclick="SubmitButtonOnclick()">Submit</button>
</div>
<input type="hidden" name="username" id="username" value="#Model.Username"/>
<fieldset>
<legend>Edit Photos</legend>
<div>
Select profile picture:
<input id="imageFile" type="file" name="imageFile" accept="image/png, image/jpeg" />
#Html.CheckBoxFor(modelItem => modelItem.DefaultCover)<span>Remove profile photo</span>
</div>
<div>
Select cover picture:
<input id="coverFile" type="file" name="coverFile" accept="image/png, image/jpeg" />
#Html.CheckBoxFor(modelItem => modelItem.DefaultCover)<span>RemoveCover</span>
</div>
</fieldset>
}
Any tips, link or code example would be useful.
Thank you in advance!

Instead of Jquery Ajax you could use
<script>
function SubmitButtonOnclick()
{
var formData= new FormData();
var imagefile=document.getElementById("imageFile").files[0];
var coverfile=document.getElementById("coverFile").files[0];
formData.append("imageFile",imageFile);
formData.append("coverFile",coverFile);
var xhr = new XMLHttpRequest();
xhr.open("POST", "/Profile/EditProfile", true);
xhr.addEventListener("load", function (evt) { UploadComplete(evt); }, false);
xhr.addEventListener("error", function (evt) { UploadFailed(evt); }, false);
xhr.send(formData);
}
function UploadComplete(evt) {
if (evt.target.status == 200)
alert("Logo uploaded successfully.");
else
alert("Error Uploading File");
}
function UploadFailed(evt) {
alert("There was an error attempting to upload the file.");
}
</script>
This works for me !!
Your script with changes
function SubmitButtonOnclick() {
var formData = new FormData();
var file = document.getElementById("imageFile").files[0];
var file1 = document.getElementById("coverFile").files[0];
formData.append("imageFile", file);
formData.append("coverfile", file1);
$.ajax({
type: "POST",
url: '#Url.Action("EditProfile","Default1")',
data: formData,
dataType: 'json',
contentType: false,
processData: false,
success: function (response) {
$('#GeneralSection').html(response.responseText);
},
error: function (error) {
$('#GeneralSection').html(error.responseText);
}
});
}

<input type="file" id="picfile" name="picf" />
<input type="text" id="txtName" style="width: 144px;" />
$("#btncatsave").click(function () {
var Name = $("#txtName").val();
var formData = new FormData();
var totalFiles = document.getElementById("picfile").files.length;
var file = document.getElementById("picfile").files[0];
formData.append("FileUpload", file);
formData.append("Name", Name);
$.ajax({
type: "POST",
url: '/Category_Subcategory/Save_Category',
data: formData,
dataType: 'json',
contentType: false,
processData: false,
success: function (msg) {
alert(msg);
},
error: function (error) {
alert("errror");
}
});
});
[HttpPost]
public ActionResult Save_Category()
{
string Name=Request.Form[1];
if (Request.Files.Count > 0)
{
HttpPostedFileBase file = Request.Files[0];
}
}

I was able to upload file through jquery using the iframe, I explained the same in my blog post, please follow the link to get the answer.
http://kaushikghosh12.blogspot.com/2014/02/ajax-fileupload-on-all-browsers.html

Related

Values from Json for Jquery autocomplete

I'm a fairly new to JQuery, Json, and MVC. I am trying to a get the autocomplete to work in a text-box (with a drop-down). This is for a parameter value selection used in a web report. The data-table values are in the model called 'BSNList'. THen in the .cshtml View, the BSN text values have to be put to a var for the jquery function to run the autocomplete - I have it working with a inline list to test the autocomplete. But, I can't get the BSNList values to work in the jquery script- even trying with a JsonConvert.SerializeObject here is my code
birthCertificateModel.BSNList = new SelectList(_jobsParamData.AsDataView(), "JobId", "BSN");
birthCertificateModel.JSONresult = JsonConvert.SerializeObject(_jobsParamData);
return View(birthCertificateModel);
<div class="col-md-2">
#*<div class="ui-widget">*#
<label for="tags">BSNs: </label>
<input id="tags" class="ui-autocomplete-input" name="tags">
#*</div>*#
#Html.LabelFor(m => m.BSNName, ReportCaptions.BSN) <br />
#Html.ListBoxFor(m => m.BSNName,
Model.BSNList,
new { #class = "ListBox", size = 8 })
</div>
<script type="text/javascript">
var jsonBSNList;
jsonBSNList = #Model.BSNList.DataTextField;
$(document).ready(function () {
$(function () {
$("#tags").autocomplete({
source: jsonBSNList
});
});
});
`
Figured this out - here is my controller , html and script - I think the ajax is where I stumbled first.
[HttpPost]
public JsonResult SerialNumberLookup(string serialNumberString)
{
using (SqlConnection conn = new SqlConnection(this.connstr))
{
List<string> serialNumberList = new List<string>();
using (SqlCommand cmd =
new SqlCommand(BuildJobStatusModel.LookupSQLSelect, conn))
{
conn.Open();
cmd.Parameters.AddWithValue("#SearchText", serialNumberString);
SqlDataReader sqlDataReader = cmd.ExecuteReader();
while (sqlDataReader.Read())
{
serialNumberList.Add(sqlDataReader["SerialNumber"].ToString());
}
return this.Json(serialNumberList, JsonRequestBehavior.AllowGet);
}
}
<br />
#Html.LabelFor(model => model.SelectedSerialNumber, ReportCaptions.SerialNumber + " Look-up:")
#Html.TextBoxFor(model => model.SelectedSerialNumber, htmlAttributes: new { #id = "autocompleteSerialNumber" })
<br />
$("#autocompleteSerialNumber").autocomplete(
{
minLength: minSearchLen,
source: function (request, response) {
$.ajax({
url: "/Reports/SerialNumberLookup",
type: "POST",
// contentType: "application/json; charset=utf-8",
dataType: "json",
data: { SerialNumberString: request.term },
dataFilter: function (data) { return data; },
success: function (data) {
response($.map(data, function (item) {
return {
value: item
};
}))
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert(textStatus);
}
})
}
});

asp net mvc ajax file upload with antiforgerytoken and without formData

I have an asp.net mvc application and want to upload files and form data with ajax and also want to use [ValidateAntiForgeryToken]-Attribute. But i not want use formData class client side (because of brower support).
My client code:
function sendMessage(id) {
if (window.FormData !== undefined) { //
var fileData = new FormData();
fileData.append('profileId', id);
fileData.append('title', $('#Message_Title').val());
fileData.append('text', $('#Message_Text').val());
fileData.append('__RequestVerificationToken', $('[name=__RequestVerificationToken]').val());
var files = $("#Message_Image").get(0).files;
if (files[0]) {
fileData.append(files[0].name, files[0]);
}
$.ajax({
url: '/Manage/SendMessage',
type: "POST",
contentType: false,
processData: false,
data: fileData,
success: function (result) {
alert(result);
},
error: function (err) {
alert(err.statusText);
}
});
} else {
var files2 = $("#Message_Image").get(0).files;
$.ajax({
url: '/Manage/SendMessage',
type: 'POST',
//contentType: false,
//processData: false,
data: {
profileId: id,
title: $('#Message_Title').val(),
text: $('#Message_Text').val(),
//image: files2[0], <--- IF I UNCOMMENT THIS IT NOT WORKS ANYMORE
__RequestVerificationToken: $('[name=__RequestVerificationToken]').val()
},
success: function (result) {
},
error: function (err) {
alert(err.statusText);
}
});
}
};
Server code:
[HttpPost]
[ValidateAntiForgeryToken]
public JsonResult SendMessage(int? profileId, string title, string text)
{
HttpPostedFileBase file = Request.Files["Image"];
HttpFileCollectionBase files = Request.Files;
return Json(null, "text/html");
}

Posting files and model to controller in ASP.NET Core MVC6

I'm migrating a project from ASP.NET RC1 to ASP.NET Core 1.0.
I have a view that allows users to upload one of more files, which I post using Jquery Ajax. I also serialize and post some settings within the same post.
The following all worked in RC1 (and pre-asp.net core):
Js:
$('#submit').click(function () {
var postData = $('#fields :input').serializeArray();
var fileSelect = document.getElementById('file-select');
var files = fileSelect.files;
var data = new FormData();
for (var i = 0; i < files.length; i++) {
data.append('file' + i, files[i]);
}
$.each(postData, function (key, input) {
data.append(input.name, input.value);
});
var url = '/ajax/uploadfile';
$.ajax({
url: url,
type: "POST",
contentType: false,
processData: false,
cache: false,
data: data,
success: function (result) {
alert('success');
},
error: function () {
alert('error');
}
});
});
Controller:
public IActionResult UploadFile(UploadFileModel model)
{
var result = new JsonResultData();
try
{
if (Request.Form.Files.Count > 0)
{
IFormFile file = Request.Form.Files[0];
//etc
}
}
}
So the above does not work anymore, no file uploaded and no model bound.
I managed to fix half the issues so now I can get the model to bind with the following code. However, the controller will still give me an exception on the Request.Files. I added the 'headers' property, and I used serializeObject (custom method). In the controller I added FromBody.
Js:
$('#submit').click(function () {
var postData = $('#fields :input').serializeArray();
var fileSelect = document.getElementById('file-select');
var files = fileSelect.files;
var data = new FormData();
for (var i = 0; i < files.length; i++) {
data.append('file' + i, files[i]);
}
$.each(postData, function (key, input) {
data.append(input.name, input.value);
});
var url = '/ajax/uploadfile';
$.ajax({
url: url,
type: "POST",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
processData: false,
cache: false,
data: serializeAndStingifyArray(data),
success: function (result) {
alert('success');
},
error: function () {
alert('error');
}
});
});
function serializeAndStingifyArray(array) {
var o = {};
var a = array;
$.each(a, function () {
if (o[this.name] !== undefined) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
o[this.name].push(this.value || '');
} else {
o[this.name] = this.value || '';
}
});
return JSON.stringify(o);
};
Controller:
[HttpPost]
public IActionResult UploadFile([FromBody]UploadFileModel model)
{
var result = new JsonResultData();
try
{
if (Request.Form.Files.Count > 0)
{
IFormFile file = Request.Form.Files[0];
//etc
}
}
}
html:
<div id="file-list">
<input type="file" name="file" class="file-select" accept="application/pdf,application">
<input type="file" name="file" class="file-select" accept="application/pdf,application" />
</div>
I started from this article which has some code that is almost the same as yours Upload Files In ASP.NET Core 1.0 (see Ajax case).
That worked for me fine on 1.0.0, so I implemented your changes and what I saw is that it failed to send the files in the request (client side issue).
This is how the payload should look like when working ok using F12 in chrome: (not sure why the file contents are hidden by chrome).
A little debugging and you are passing wrong data to data.append
The fix is in this line
$(".file-select").each(function () { data.append($(this).val(), $(this).get(0).files[0]); i++; })
Full code:
$(document).ready(function () {
$("#submit").click(function (evt) {
var data = new FormData();
i = 0;
$(".file-select").each(function () { data.append($(this).val(), $(this).get(0).files[0]); i++; })
var postData = $('#fields :input');
$.each(postData, function (key, input) {
data.append(input.name, input.value);
});
$.ajax({
type: "POST",
url: "/ajax/uploadfile", // <--- Double check this url.
contentType: false,
processData: false,
data: data,
success: function (message) {
alert(message);
},
error: function () {
alert("There was error uploading files!");
}
});
});
});
No need to use [FromBody] or serializeArray()
[HttpPost]
public IActionResult UploadFilesAjax(MyViewModel xxx )
{
This is my html, just in case:
<form method="post" enctype="multipart/form-data">
<div id="file-list">
<input type="file" name="file" class="file-select" accept="application/pdf,application">
<input type="file" name="file" class="file-select" accept="application/pdf,application" />
</div>
<div id="fields">
<input type="text" name="Email" />
</div>
<input type="button"
id="submit"
value="Upload Selected Files" />
</form>

Refresh page after POST

I have created a solution where I post an array of string to my controller.
The setup works fine but I have to manually refresh the page before I can see the results of my method.
How do I make the solution refresh the page after I posted?
My view (tree.html):
<form>
<textarea class="form-control auto-input-field" rows="10" cols="80" id="autoGenerateInputField" ng-model="fighterList" ng-list="/\n/" />
<input class="btn btn-primary" type="submit" ng-click="GenerateTournamentTree(data)" value="Generer kamptræ" />
</form>
My js (angular):
$scope.GenerateTournamentTree = function(matches){
var stringOfFighters = new Array();
var categoryId = $scope.CategoryId;
stringOfFighters = $scope.fighterList;
var postData = { fighters: stringOfFighters };
if (stringOfFighters != null) {
$.ajax({
type: "POST",
url: "/Api/Match/GenerateTournamentTree",
contentType: 'application/json; charset=utf-8',
data: JSON.stringify(stringOfFighters),
success: function (data) {
alert(data.Result);
},
dataType: "json",
traditional: true
});
} else {
$modal.open({
templateUrl: 'generateTreeMessage.html',
scope: $scope,
controller: function ($scope) {
$scope.ok = function () {
$scope.$dismiss();
}
$scope.cancel = function () {
$scope.$dismiss();
}
}
})
}
}
My controller:
[Route("api/Match/GenerateTournamentTree")]
public IHttpActionResult GenerateTournamentTree(List<String> fighters)
{
fighters.Shuffle();
var nodeTree = InsertNode(new TreeNode(), fighters);
var matches = new List<MatchRecord>();
GenerateMatch(matches, nodeTree);
foreach(var match in matches)
{
match.CategoryId = new Guid("425d750e-56bd-412c-8a48-38c2fbe5b24c");
match.EventId = 18;
}
db.Matches.AddRange(matches);
try
{
db.SaveChanges();
}
catch (DbUpdateException)
{
throw;
}
//return CreatedAtRoute("DefaultApi", new { id = "18" }, fighters);
//I tried this but with no succes.
return Json(new { Result = fighters });
//this is only created to return something.
}

how to send upload control data to jquery ajax wihout plugins

I am trying to upload file/files to server through Ajax request in MVC, but the file is always returning null in the controller, can you please suggest the way to pass the file data in the ajax request?
<form method="post" enctype="multipart/form-data">
<div>
#Html.AntiForgeryToken()
<input type="file" name="file" id="files" multiple><br>
<input type="button" value="Upload File to Server" id="submit">
</div>
</form>
<script type="text/javascript">
$("#submit").click(function () {
var formData = $('#files').val();
alert(formData);
$.ajax({
url: 'home/index',
type: 'POST',
datatype: 'json',
enctype: "multipart/form-data",
data: { file: formData },
//processData: false, // Don't process the files
//contentType: false, // Set content type to false as jQuery will tell the server its a query string request
success: function (data) {
alert(data);
},
error: function () {
alert("failed");
}
});
});
</script>
[HttpPost]
[ActionName("Index")]
public ActionResult Index_Post(HttpPostedFileBase file)
{
string errormsg = string.Empty;
if (file != null)
{
// Verify that the user selected a file
if (file != null && file.ContentLength > 0)
{
// extract only the fielname
var fileName = Path.GetFileName(file.FileName);
// TODO: need to define destination
var path = Path.Combine(Server.MapPath("~/Upload"), fileName);
try
{
file.SaveAs(path);
errormsg = "uploaded";
return Json(fileName + errormsg);
}
catch
{
errormsg = "failed to upload";
return Json(fileName + errormsg);
}
}
}
else
{
errormsg = "No file selected";
return Json(errormsg);
}
return View();
}
}
Take normal button instead of submit button and try below code
$("#submit").click(function () {
var formData = new FormData();
var opmlFile = $('#myFile')[0];
formData.append("opmlFile", opmlFile.files[0]);
$.ajax({
url: 'home/index',
type: 'POST',
datatype: 'json',
enctype: "multipart/form-data",
data: formData ,
//processData: false, // Don't process the files
//contentType: false, // Set content type to false as jQuery will tell the server its a query string request
success: function (data) {
alert(data);
},
error: function () {
alert("failed");
}
});
});
});
and controller action :-
[HttpPost]
[ActionName("Index")]
public HttpResponseMessage Index()
{
HttpResponseMessage result = null;
var httpRequest = HttpContext.Current.Request;
// Check if files are available
if (httpRequest.Files.Count > 0)
{
var files = new List<string>();
// interate the files and save on the server
foreach (string file in httpRequest.Files)
{
var postedFile = httpRequest.Files[file];
var filePath = HttpContext.Current.Server.MapPath("~/" + postedFile.FileName);
postedFile.SaveAs(filePath);
files.Add(filePath);
}
// return result
result = Request.CreateResponse(HttpStatusCode.Created, files);
}
else
{
// return BadRequest (no file(s) available)
result = Request.CreateResponse(HttpStatusCode.BadRequest);
}
return result;
}

Categories