Can't get jQuery and web service to play nice - javascript

I've built a simple Bootstrap login form in an ASP.NET WebForms app, like so:
<%# Page Title="" Language="C#" MasterPageFile="~/Main.master" AutoEventWireup="true" CodeFile="test.aspx.cs" Inherits="test" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
<script type="text/javascript">
$(document).ready(function () {
$('#signInBtn').click( function () {
if ($('#MemberName').val() == "" || $('#Password').val() == "") {
e.preventDefault();
return false;
}
var $btn = $(this);
$btn.button('loading');
var formData = {};
formData['MemberName'] = $('#MemberName').val();
formData['Password'] = $('#Password').val();
var json = JSON.stringify({ Member: formData });
$.ajax({
url: "members.asmx/ValidateLogin",
timeout: 30000,
type: 'POST',
data: json,
dataType: 'json',
contentType: "application/json; charset=utf-8",
success: function (data) {
var response = JSON.parse(data.d);
alert(response);
},
error: function (data, textStatus, jqXHR) {
var obj = jQuery.parseJSON(jqXHR.responseText);
alert(obj);
}
})
});
});
</script>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="cpMain" Runat="Server">
<div id="frm">
<div class="form-inline form-group-sm">
<div class="input-group">
<label for="MemberName" class="sr-only">Email Address :</label>
<span class="input-group-addon"><span class="glyphicon glyphicon-user"></span></span>
<input type="email" required id="MemberName" placeholder="Email Address" class="form-control">
</div>
<div class="input-group">
<label for="Password" class="sr-only">Password :</label>
<input type="password" required id="Password" placeholder="Password" class="form-control">
</div>
<button id="signInBtn" class="btn-sm btn-primary" autocomplete="off" data-loading-text="Wait...">Login</button>
</div>
</div>
</asp:Content>
It connects to a web service, with the following code:
using System;
using System.Collections.Generic;
using System.Web.Services;
using System.Web.Script.Services;
using Newtonsoft.Json;
using MCV.Data;
[WebService(Namespace = "http:/myproject.temp.com/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.Web.Script.Services.ScriptService]
public class Members : System.Web.Services.WebService
{
public Members()
{ }
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public string ValidateLogin(Member NewMember)
{
string name = NewMember.MemberName;
SignInResponse r;
try
{
bool status = MemberDB.SignIn(NewMember.MemberName, NewMember.Password);
if (status)
r = new SignInResponse("1", "OK");
else
r = new SignInResponse("0", "ERR");
}
catch (Exception ex)
{
r = new SignInResponse("-1", ex.Message);
}
return JsonConvert.SerializeObject(r);
}
}
This is not complicated code. The web service simply calls a method in another class to validate the user's email and password and returns a JSON string containing a custom class with the result of the validation.
The problem is, the code fails silently. It doesn't appear to fail, because the Chrome console shows no errors. I added a breakpoint in the web service code to see what it was doing, but the breakpoint is never hit. I don't know where the error is, but it's driving me loopy.
Any thoughts on this?

Two issues:
You're not passing through the NewMember parameter correctly from $.ajax
Pay attention to the spelling of the .asmx file, in your javascript you call it members.asmx/ValidateLogin but in the C# code behind it's called Members with a capital M.Make sure that the case matches.
I just made a change to correctly build up the NewMember from javascript and made sure that the .asmx file in my solution is called members.asmx and it's working now:
$('#signInBtn').click(function () {
if ($('#MemberName').val() == "" || $('#Password').val() == "") {
e.preventDefault();
return false;
}
var json = {
"MemberName": $('#MemberName').val(),
"Password": $('#Password').val()
};
$.ajax({
url: "members.asmx/ValidateLogin",
timeout: 30000,
type: 'POST',
data: JSON.stringify({ NewMember: json }),
dataType: 'json',
contentType: "application/json; charset=utf-8",
success: function (data) {
var response = JSON.parse(data.d);
alert(response);
},
error: function (data, textStatus, jqXHR) {
var obj = jQuery.parseJSON(jqXHR.responseText);
alert(obj);
}
})
});

Related

Javascript function to validate form by ASP.NET Core Jquery validation

I'm trying to validate an ASP.NET Core form without refreshing the page by ASP.NET Core JQuery validation (the one provided in the project). The validation is working properly when I post the form normally. But I want to post the form with AJAX, so I run the preventDefault() js function to do the submission manually by ajax. But it seems that this function is breaking the validation (The one that works without refresh). It means that even if the form has errors, it submits!
This is my cshtml file:
#page
#model Baunity.Web.Pages.Dash.EditProfileModel
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
<p id="verificationAlert" style="display: none !important;" class="alert alert-success">text</p>
#section Scripts {
#{
await Html.RenderPartialAsync ("_ValidationScriptsPartial");
}
}
<form method="post">
<input asp-for="Email" />
<label asp-for="Email"></label>
<span asp-validation-for="Email"></span>
<br />
<input asp-for="Username" />
<label asp-for="Username"></label>
<span asp-validation-for="Username"></span>
<br />
<input asp-for="Password" />
<label asp-for="Password"></label>
<span asp-validation-for="Password"></span>
<br />
<input asp-for="ConfirmPassword" />
<label asp-for="ConfirmPassword"></label>
<span asp-validation-for="ConfirmPassword"></span>
<br />
<input asp-for="FirstName" />
<label asp-for="FirstName"></label>
<span asp-validation-for="FirstName"></span>
<br />
<input asp-for="LastName" />
<label asp-for="LastName"></label>
<span asp-validation-for="LastName"></span>
<br />
<div id="verificationForm" style="display: none !important;">
<input asp-for="VerificationCode" />
<label asp-for="VerificationCode"></label>
<span asp-validation-for="VerificationCode"></span>
</div>
<div asp-validation-summary="ModelOnly"></div>
<br />
FIX DOING OTHER STUFF LIKE SETTING VALUES AT BACKEND
<input type="submit" id="submit" onclick="SubmitForm(this.parentElement, event)" />
</form>
<p>#ViewData["DONE"]</p>
site.js
let isVerificationEmailSent = false;
function SubmitForm(frm, caller) {
debugger;
if (!isVerificationEmailSent) {
caller.preventDefault();
}
else {
return;
}
var fdata = new FormData();
var emailData = $('#Email').val();
fdata.append("Email", emailData);
var usernameData = $('#Username').val();
fdata.append("Username", usernameData);
var passwordData = $('#Password').val();
fdata.append("Password", passwordData);
var confirmPasswordData = $('#ConfirmPassword').val();
fdata.append("ConfirmPassword", confirmPasswordData);
var firstNameData = $('#FirstName').val();
fdata.append("FirstName", firstNameData);
var lastNameData = $('#LastName').val();
fdata.append("LastName", lastNameData);
let isSuccess = true;
$.ajax(
{
type: frm.method,
url: frm.action,
headers:
{
"XSRF-TOKEN": $("input[name='__RequestVerificationToken']").val()
},
data: fdata,
processData: false,
contentType: false,
statusCode: {
912: function (responseObject, textStatus, jqXHR) {
$("#verificationForm").show();
$("#verificationAlert").show();
isVerificationEmailSent = true;
},
},
success: function (data) {
alert(data);
isSuccess = true;
},
error: function (data) {
if (!isSuccess) {
alert('ERROR' + data);
}
}
})
}
I've tried to use valid() & validate() function in jquery, but it gave me error. I want a method similar to these two.
If you don't wanna use submit button to submit the form, Why do you set the type="submit"? You can just set the button like:
<button type="button" onclick="SubmitForm(this.parentElement)">submit</button>
In this case, You don't need to use event.preventDefault() anymore.
set an id for the form:
<form method="post" Id="Form">...</form>
Then in your js code:
let isVerificationEmailSent = false;
function SubmitForm(frm) {
$('#Form').validate();
if ($('#Form').valid() === true) {
var fdata = new FormData();
var emailData = $('#Email').val();
fdata.append("Email", emailData);
var usernameData = $('#Username').val();
fdata.append("Username", usernameData);
var passwordData = $('#Password').val();
fdata.append("Password", passwordData);
var confirmPasswordData = $('#ConfirmPassword').val();
fdata.append("ConfirmPassword", confirmPasswordData);
var firstNameData = $('#FirstName').val();
fdata.append("FirstName", firstNameData);
var lastNameData = $('#LastName').val();
fdata.append("LastName", lastNameData);
let isSuccess = true;
$.ajax(
{
type: frm.method,
url: frm.action,
headers:
{
"XSRF-TOKEN": $("input[name='__RequestVerificationToken']").val()
},
data: fdata,
processData: false,
contentType: false,
statusCode: {
912: function (responseObject, textStatus, jqXHR) {
$("#verificationForm").show();
$("#verificationAlert").show();
isVerificationEmailSent = true;
},
},
success: function (data) {
alert(data);
isSuccess = true;
},
error: function (data) {
if (!isSuccess) {
alert('ERROR' + data);
}
}
})
}
}

Submit a Form using AJAX in ASP.Net Core MVC

I am working with ASP.Net Core 2.1, and trying to upload a file while returning it's url, without refreshing the page.
I am trying to write the JavaScript in site.js as the _RenderPartial("scripts") renders all scripts at the end of the page and hence directly using script tag in the razor view is not working. Secondly, adding it to site.js gives me an opportunity to call the script across the site views.
My Controller action looks like :
[HttpPost]
[DisableRequestSizeLimit]
public async Task<IActionResult> Upload()
{
// Read & copy to stream the content of MultiPart-Form
// Return the URL of the uploaded file
return Content(FileName);
}
My view looks like :
<form id="FileUploadForm" action="~/Resources/Upload" method="post" enctype="multipart/form-data">
<input name="uploadfile" type="file" />
<button name="uploadbtn" type="submit" onclick="SubmitForm(this.parentElement, event)">Upload</button>
The site.js currently looks like :
function SubmitForm(form, caller) {
caller.preventDefault();
$.ajax(
{
type: form.method,
url: form.action,
data: form.serialize(),
success: function (data) { alert(data); },
error: function (data) { alert(data); }
})}
Presently, the code bypasses the entire script and the file is uploaded and new view displaying the file name is returned. I need help to create the javascript.
Unfortunately the jQuery serialize() method will not include input file elements. So the file user selected is not going to be included in the serialized value (which is basically a string).
What you may do is, create a FormData object, append the file(s) to that. When making the
ajax call, you need to specify processData and contentType property values to false
<form id="FileUploadForm" asp-action="Upload" asp-controller="Home"
method="post" enctype="multipart/form-data">
<input id="uploadfile" type="file" />
<button name="uploadbtn" type="submit">Upload</button>
</form>
and here in the unobutrusive way to handle the form submit event where we will stop the regular behavior and do an ajax submit instead.
$(function () {
$("#FileUploadForm").submit(function (e) {
e.preventDefault();
console.log('Doing ajax submit');
var formAction = $(this).attr("action");
var fdata = new FormData();
var fileInput = $('#uploadfile')[0];
var file = fileInput.files[0];
fdata.append("file", file);
$.ajax({
type: 'post',
url: formAction,
data: fdata,
processData: false,
contentType: false
}).done(function (result) {
// do something with the result now
console.log(result);
if (result.status === "success") {
alert(result.url);
} else {
alert(result.message);
}
});
});
})
Assuming your server side method has a parameter of with name same as the one we used when we created the FormData object entry(file). Here is a sample where it will upload the image to the uploads directory inside wwwwroot.
The action method returns a JSON object with a status and url/message property and you can use that in the success/done handler of the ajax call to whatever you want to do.
public class HomeController : Controller
{
private readonly IHostingEnvironment hostingEnvironment;
public HomeController(IHostingEnvironment environment)
{
_context = context;
hostingEnvironment = environment;
}
[HttpPost]
public async Task<IActionResult> Upload(IFormFile file)
{
try
{
var uniqueFileName = GetUniqueFileName(file.FileName);
var uploads = Path.Combine(hostingEnvironment.WebRootPath, "uploads");
var filePath = Path.Combine(uploads, uniqueFileName);
file.CopyTo(new FileStream(filePath, FileMode.Create));
var url = Url.Content("~/uploads/" + uniqueFileName);
return Json(new { status = "success", url = url });
}
catch(Exception ex)
{
// to do : log error
return Json(new { status = "error", message = ex.Message });
}
}
private string GetUniqueFileName(string fileName)
{
fileName = Path.GetFileName(fileName);
return Path.GetFileNameWithoutExtension(fileName)
+ "_"
+ Guid.NewGuid().ToString().Substring(0, 4)
+ Path.GetExtension(fileName);
}
}
Sharing the code that worked for me, implementing #Shyju's answer.
View ( Razor Page ):
<form name="UploadForm" action="~/Resources/Upload" method="post" enctype="multipart/form-data">
<input name="uploadfile" type="file" />
<button name="uploadbtn" type="submit" onclick="SubmitForm(this.parentElement, event)">Upload</button>
AJAX code added in Site.js (to make it a reusable):
// The function takes Form and the event object as parameter
function SubmitForm(frm, caller) {
caller.preventDefault();
var fdata = new FormData();
var file = $(frm).find('input:file[name="uploadfile"]')[0].files[0];
fdata.append("file", file);
$.ajax(
{
type: frm.method,
url: frm.action,
data: fdata,
processData: false,
contentType: false,
success: function (data) {
alert(data);
},
error: function (data) {
alert(data);
}
})
};
if you want to submit the form without using ajax request
var form = document.getElementById('formId');
form.submit();

Postback event on text changed event

I want to postback on every keypress/textchanged event in textbox but my javascript is not running. Am i missing something...????
My Html textbox is this:
<asp:TextBox ID="Txt_Search" runat="server" AutoCompleteType="Disabled"
onkeypress="Postback();" OnTextChanged="Txt_Search_TextChanged" AutoPostBack="true">
</asp:TextBox>
My Javascript code is this:
function Postback() {
__doPostBack('<%= Txt_Search.ClientID %>', '');
};
My on textchanged event is this:
protected void Txt_Search_TextChanged(object sender, EventArgs e)
{
FolderStructure.Nodes.Clear();
Searchtxt();
}
I create sample projects ASP.NET WebForms and AJAX.
I Suggest you can use AJAX process .NET Generic Handler File. Please you research about Generic Handler file.
Before create Generic Handler file "Search.ashx" and Paste above the code.
public void ProcessRequest(HttpContext context)
{
var search = HttpContext.Current.Request.Form["term"];
//Dummy Data
List<string> searchList = new List<string> { "Red", "Orange", "Ping", "Blue", "White", "Black" };
string result = string.Empty;
if (!string.IsNullOrEmpty(search))
{
searchList = searchList.Where(x => x.ToLower().Contains(search.ToLower())).ToList();
if (searchList != null && searchList.Count() > 0)
{
foreach (var item in searchList)
{
result += "<li>" + item + "</li>";
}
}
}
else
{
result="<li> Not Found </li>";
}
context.Response.ContentType = "text/plain";
context.Response.Write(result);
}
public bool IsReusable
{
get
{
return false;
}
}
and Create Your Search Page, YourFile.aspx, my file name Search.aspx.
ASPX Page Code :
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication7.Default" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<input type="text" id="txtSearch" class="js-search" value="Search" />
<div class="searchResult">
<ul>
</ul>
</div>
</div>
</form>
<script src="https://code.jquery.com/jquery-2.2.3.min.js" type="text/javascript"></script>
<script>
$(function () {
$(".js-search").on('keyup', function () {
var term = $('.js-search').val();
if (term.length > 2) {
sendSearchRequest({ "term": term });
}
});
function sendSearchRequest(value) {
var datas = $.ajax({
type: "POST",
url: '/Search.ashx',
cache: false,
async: false,
data: value,
success: function (term) {
$('.searchResult').empty();
$('.searchResult').append(term);
}
});
}
});
</script>
</body>
</html>
This example when all three letters entered send ajax request search.ashx file and contains search term and get result on search page.
I hope that helps.
Modify code as below and check
__doPostBack('Txt_Search', '');
here is demo for dynamic search in asp.net.
Your textbox should be:
<asp:TextBox ID="PopertyName" placeholder="Property Name" href="#"
propertyid="" runat="server" class="dropdownAnchor"
autocomplete="off" onkeydown="SearchProperty()"></asp:TextBox>
here we will call a function named searchProperty() onkeydown event.
so, your ajax should be,
function SearchProperty() {
$.ajax({
url: '<%=Page.ResolveUrl("~/Dashboard/NewDashboard.aspx/GetProperty") %>',
data: "{ 'prefix': '" + $("#PopertyName").val() + "'}",
dataType: "json",
type: "POST",
contentType: "application/json; charset=utf-8",
success: function (data) {
//Your code to bind result that received from your back end.
},
error: function (response) {
alert(response.responseText);
},
failure: function (response) {
alert(response.responseText);
}
});
};
these function will call a GetPoprty() method on newDashboard.aspx.cs file.
so my back end method is,
[WebMethod]
public static List<Model.Property> GetProperty(string prefix)
{
// Here you get your text in prefix
}

XMLHTTPREQUEST send file and parameters [duplicate]

I'm using jQuery and Ajax for my forms to submit data and files but I'm not sure how to send both data and files in one form?
I currently do almost the same with both methods but the way in which the data is gathered into an array is different, the data uses .serialize(); but the files use = new FormData($(this)[0]);
Is it possible to combine both methods to be able to upload files and data in one form through Ajax?
Data jQuery, Ajax and html
$("form#data").submit(function(){
var formData = $(this).serialize();
$.ajax({
url: window.location.pathname,
type: 'POST',
data: formData,
async: false,
success: function (data) {
alert(data)
},
cache: false,
contentType: false,
processData: false
});
return false;
});
<form id="data" method="post">
<input type="text" name="first" value="Bob" />
<input type="text" name="middle" value="James" />
<input type="text" name="last" value="Smith" />
<button>Submit</button>
</form>
Files jQuery, Ajax and html
$("form#files").submit(function(){
var formData = new FormData($(this)[0]);
$.ajax({
url: window.location.pathname,
type: 'POST',
data: formData,
async: false,
success: function (data) {
alert(data)
},
cache: false,
contentType: false,
processData: false
});
return false;
});
<form id="files" method="post" enctype="multipart/form-data">
<input name="image" type="file" />
<button>Submit</button>
</form>
How can I combine the above so that I can send data and files in one form via Ajax?
My aim is to be able to send all of this form in one post with Ajax, is it possible?
<form id="datafiles" method="post" enctype="multipart/form-data">
<input type="text" name="first" value="Bob" />
<input type="text" name="middle" value="James" />
<input type="text" name="last" value="Smith" />
<input name="image" type="file" />
<button>Submit</button>
</form>
The problem I had was using the wrong jQuery identifier.
You can upload data and files with one form using ajax.
PHP + HTML
<?php
print_r($_POST);
print_r($_FILES);
?>
<form id="data" method="post" enctype="multipart/form-data">
<input type="text" name="first" value="Bob" />
<input type="text" name="middle" value="James" />
<input type="text" name="last" value="Smith" />
<input name="image" type="file" />
<button>Submit</button>
</form>
jQuery + Ajax
$("form#data").submit(function(e) {
e.preventDefault();
var formData = new FormData(this);
$.ajax({
url: window.location.pathname,
type: 'POST',
data: formData,
success: function (data) {
alert(data)
},
cache: false,
contentType: false,
processData: false
});
});
Short Version
$("form#data").submit(function(e) {
e.preventDefault();
var formData = new FormData(this);
$.post($(this).attr("action"), formData, function(data) {
alert(data);
});
});
another option is to use an iframe and set the form's target to it.
you may try this (it uses jQuery):
function ajax_form($form, on_complete)
{
var iframe;
if (!$form.attr('target'))
{
//create a unique iframe for the form
iframe = $("<iframe></iframe>").attr('name', 'ajax_form_' + Math.floor(Math.random() * 999999)).hide().appendTo($('body'));
$form.attr('target', iframe.attr('name'));
}
if (on_complete)
{
iframe = iframe || $('iframe[name="' + $form.attr('target') + '"]');
iframe.load(function ()
{
//get the server response
var response = iframe.contents().find('body').text();
on_complete(response);
});
}
}
it works well with all browsers, you don't need to serialize or prepare the data.
one down side is that you can't monitor the progress.
also, at least for chrome, the request will not appear in the "xhr" tab of the developer tools but under "doc"
I was having this same issue in ASP.Net MVC with HttpPostedFilebase and instead of using form on Submit I needed to use button on click where I needed to do some stuff and then if all OK the submit form so here is how I got it working
$(".submitbtn").on("click", function(e) {
var form = $("#Form");
// you can't pass Jquery form it has to be javascript form object
var formData = new FormData(form[0]);
//if you only need to upload files then
//Grab the File upload control and append each file manually to FormData
//var files = form.find("#fileupload")[0].files;
//$.each(files, function() {
// var file = $(this);
// formData.append(file[0].name, file[0]);
//});
if ($(form).valid()) {
$.ajax({
type: "POST",
url: $(form).prop("action"),
//dataType: 'json', //not sure but works for me without this
data: formData,
contentType: false, //this is requireded please see answers above
processData: false, //this is requireded please see answers above
//cache: false, //not sure but works for me without this
error : ErrorHandler,
success : successHandler
});
}
});
this will than correctly populate your MVC model, please make sure in your Model, The Property for HttpPostedFileBase[] has the same name as the Name of the input control in html i.e.
<input id="fileupload" type="file" name="UploadedFiles" multiple>
public class MyViewModel
{
public HttpPostedFileBase[] UploadedFiles { get; set; }
}
Or shorter:
$("form#data").submit(function() {
var formData = new FormData(this);
$.post($(this).attr("action"), formData, function() {
// success
});
return false;
});
EDIT: with the new version of JQuery (3.6), you could also try using contentType function argument instead of enctype. Try contentType: multipart/form-data.
For me, it didn't work without enctype: 'multipart/form-data' field in the Ajax request. I hope it helps someone who is stuck in a similar problem.
Even though the enctype was already set in the form attribute, for some reason, the Ajax request didn't automatically identify the enctype without explicit declaration (jQuery 3.3.1).
// Tested, this works for me (jQuery 3.3.1)
fileUploadForm.submit(function (e) {
e.preventDefault();
$.ajax({
type: 'POST',
url: $(this).attr('action'),
enctype: 'multipart/form-data',
data: new FormData(this),
processData: false,
contentType: false,
success: function (data) {
console.log('Thank God it worked!');
}
}
);
});
// enctype field was set in the form but Ajax request didn't set it by default.
<form action="process/file-upload" enctype="multipart/form-data" method="post" >
<input type="file" name="input-file" accept="text/plain" required>
...
</form>
As others mentioned above, please also pay special attention to the contentType and processData fields.
A Simple but more effective way:
new FormData() is itself like a container (or a bag). You can put everything attr or file in itself.
The only thing you'll need to append the attribute, file, fileName eg:
let formData = new FormData()
formData.append('input', input.files[0], input.files[0].name)
and just pass it in AJAX request. Eg:
let formData = new FormData()
var d = $('#fileid')[0].files[0]
formData.append('fileid', d);
formData.append('inputname', value);
$.ajax({
url: '/yourroute',
method: 'POST',
contentType: false,
processData: false,
data: formData,
success: function(res){
console.log('successfully')
},
error: function(){
console.log('error')
}
})
You can append n number of files or data with FormData.
and if you're making AJAX Request from Script.js file to Route file in Node.js beware of using
req.body to access data (ie text)
req.files to access file (ie image, video etc)
The code below works for me
$(function () {
debugger;
document.getElementById("FormId").addEventListener("submit", function (e) {
debugger;
if (ValidDateFrom()) { // Check Validation
var form = e.target;
if (form.getAttribute("enctype") === "multipart/form-data") {
debugger;
if (form.dataset.ajax) {
e.preventDefault();
e.stopImmediatePropagation();
var xhr = new XMLHttpRequest();
xhr.open(form.method, form.action);
xhr.onreadystatechange = function (result) {
debugger;
if (xhr.readyState == 4 && xhr.status == 200) {
debugger;
var responseData = JSON.parse(xhr.responseText);
SuccessMethod(responseData); // Redirect to your Success method
}
};
xhr.send(new FormData(form));
}
}
}
}, true);
});
In your Action Post Method, pass parameter as HttpPostedFileBase UploadFile and make sure your file input has same as mentioned in your parameter of the Action Method.
It should work with AJAX Begin form as well.
Remember over here that your AJAX BEGIN Form will not work over here since you make your post call defined in the code mentioned above and you can reference your method in the code as per the Requirement
I know I am answering late but this is what worked for me
Just to remind, in 2022 you don't need to use jquery. Try js standard Fetch API
var formData = new FormData(this);
fetch(url, {
method: 'POST',
body: formData
})
.then(response => {
if(response.ok) {
//success
alert(response);
} else {
throw Error('Server error');
}
})
.catch(error => {
console.log('fail', error);
});
This is a solution that I implemented
var formData = new FormData();
var files = $('input[type=file]');
for (var i = 0; i < files.length; i++) {
if (files[i].value == "" || files[i].value == null) {
return false;
}
else {
formData.append(files[i].name, files[i].files[0]);
}
}
var formSerializeArray = $("#Form").serializeArray();
for (var i = 0; i < formSerializeArray.length; i++) {
formData.append(formSerializeArray[i].name, formSerializeArray[i].value)
}
$.ajax({
type: 'POST',
data: formData,
contentType: false,
processData: false,
cache: false,
url: '/Controller/Action',
success: function (response) {
if (response.Success == true) {
return true;
}
else {
return false;
}
},
error: function () {
return false;
},
failure: function () {
return false;
}
});
---Solution for DOT NET CORE MVC Implementation---
While looking at this question I though I should right .NET CORE implementation for this because the question is not specific to any backend language.
So guys here is the standalone implementation example.
Objective :- To submit form fields including files and how we can get data in a single model at backend
HTML Code / View Code - Views/Home/Index.cshtml
#{
ViewData["Title"] = "Home Page";
}
<input type="file" id="FileUpload1" multiple />
<div>
<label>Enter First Name :</label>
<input type="text" id="nameText" maxlength="50" />
</div>
<input type="button" id="btnUpload" value="Submit Form with Files" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script>
$(document).ready(function () {
$('#btnUpload').click(function () {
// Checking whether FormData is available in browser
if (window.FormData !== undefined) {
var fileUpload = $("#FileUpload1").get(0);
var files = fileUpload.files;
// Create FormData object
var fileData = new FormData();
// Looping over all files and add it to FormData object
for (var i = 0; i < files.length; i++) {
fileData.append("files", files[i]);
}
// Adding one more key to FormData object
fileData.append('FirstName', $("#nameText").val());
$.ajax({
url: '/Home/UploadFiles',
type: "POST",
contentType: false, // Not to set any content header
processData: false, // Not to process data
data: fileData,
success: function (result) {
alert(result);
},
error: function (err) {
alert(err.statusText);
}
});
} else {
alert("FormData is not supported.");
}
});
});
</script>
Backend Code / Controller action method Controllers/HomeController.cs
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
private readonly IWebHostEnvironment _environment;
public HomeController(ILogger<HomeController> logger, IWebHostEnvironment environment)
{
_logger = logger;
_environment = environment;
}
public IActionResult Index()
{
return View();
}
public IActionResult Privacy()
{
return View();
}
[HttpPost]
public async Task<IActionResult> UploadFiles(MyForm myForm)
{
var files = myForm.Files;
// First Name
string name = myForm.FirstName;
// check All files
foreach (IFormFile source in files)
{
string filename = ContentDispositionHeaderValue.Parse(source.ContentDisposition).FileName.Trim('"');
filename = this.EnsureCorrectFilename(filename);
string fileWithPath = this.GetPathAndFilename(filename);
// Create directory if not exist
Directory.CreateDirectory(Path.GetDirectoryName(fileWithPath));
using (FileStream output = System.IO.File.Create(fileWithPath))
await source.CopyToAsync(output);
}
return Ok("Success");
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
public class MyForm
{
public string FirstName { get; set; }
public IList<IFormFile> Files { get; set; }
}
private string EnsureCorrectFilename(string filename)
{
if (filename.Contains("\\"))
filename = filename.Substring(filename.LastIndexOf("\\") + 1);
return filename;
}
private string GetPathAndFilename(string filename)
{
return Path.Combine(_environment.ContentRootPath, "uploadedFiles", filename);
}
}
Full Source Code Repo: https://github.com/rj-learning/DotNetCoreFileUpload
In my case I had to make a POST request, which had information sent through the header, and also a file sent using a FormData object.
I made it work using a combination of some of the answers here, so basically what ended up working was having this five lines in my Ajax request:
contentType: "application/octet-stream",
enctype: 'multipart/form-data',
contentType: false,
processData: false,
data: formData,
Where formData was a variable created like this:
var file = document.getElementById('uploadedFile').files[0];
var form = $('form')[0];
var formData = new FormData(form);
formData.append("File", file);
you can just append them on your formdata, add your files and datas in it.you can read this..
https://developer.mozilla.org/en-US/docs/Web/API/FormData/append
for better understanding. you can separately retrieve them $_FILES for your files and $_POST for your data.
<form id="form" method="post" action="otherpage.php" enctype="multipart/form-data">
<input type="text" name="first" value="Bob" />
<input type="text" name="middle" value="James" />
<input type="text" name="last" value="Smith" />
<input name="image" type="file" />
<button type='button' id='submit_btn'>Submit</button>
</form>
<script>
$(document).on("click", "#submit_btn", function (e) {
//Prevent Instant Click
e.preventDefault();
// Create an FormData object
var formData = $("#form").submit(function (e) {
return;
});
//formData[0] contain form data only
// You can directly make object via using form id but it require all ajax operation inside $("form").submit(<!-- Ajax Here -->)
var formData = new FormData(formData[0]);
$.ajax({
url: $('#form').attr('action'),
type: 'POST',
data: formData,
success: function (response) {
console.log(response);
},
contentType: false,
processData: false,
cache: false
});
return false;
});
</script>
///// otherpage.php
<?php
print_r($_FILES);
?>

Ajax query to my webservices is returning xml in my json - Part 2

It's me again (previous question) I am still having problems with json and xml being returned from an ajax call.
I have written a webservice in MonoDevelop version 2.2 to return my json.
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public string getLocationJ(){}
Which returns:-
JavaScriptSerializer js = new JavaScriptSerializer();
string json = js.Serialize(bigPM);
return json;
If I test my webservice I get:-
<?xml version="1.0" encoding="utf-8"?>
<string xmlns="http://tempuri.org/">[{"placeName":"XXXX","address":"Some Address","lat":12121,"lng":12121}]</string>
Which is exactly what I am pulling in when I make my ajax calls. My json is still wrapped in XML and therefore cannot be read.
This is my ajax call:-
$.ajax({
type: "GET",
url: theURL,
async: true,
data: {minLong:minLon, maxLong:maxLon, minLat:minLat, maxLat:maxLat},
cache: false,
dataType: "jsonp",
contentType: "application/xml; charset=utf-8",
success: function (data) {
alert('in here');
},
error:function (xhr, ajaxOptions, thrownError){
alert(xhr.status);
alert(thrownError);
alert(xhr.statusText);
}
});
If I do just json I get 500 Internal server error, if I do a POST I get 403 forbidden error.
This morning I tried doing:-
$.getJSON(theURL, {minLong:minLon, maxLong:maxLon, minLat:minLat, maxLat:maxLat}, function(data) {
);
});
Only I get the exact same problems.
If I could just remove the xml from my json then I could move forward but right now I am dead in the water and I think I am drowning in ajax!
Please help
Cheryl
Instead of returning a string in your WebMethod, return void and use:
JavaScriptSerializer js = new JavaScriptSerializer();
Context.Response.Write(js.Serialize(YOUR_STRING_TO_OUTPUT));
A quick and dirty fix is to extract your json from the xml in the success function.
$.ajax({
type: "GET",
url: theURL,
async: true,
data: {minLong:minLon, maxLong:maxLon, minLat:minLat, maxLat:maxLat},
cache: false,
dataType: "jsonp",
contentType: "application/xml; charset=utf-8",
success: function (data) {
data = extractJsonFromXml(data);
//you have to write extractJsonFromXml function in js, you could use substring, or a regex replace.
}
change
contentType: "application/xml; charset=utf-8",
to
contentType: "application/json; charset=utf-8",
Complete example:
/* in this case I am using */
<script src="Js/json2.js" type="text/javascript"></script>
// available at: http://www.json.org/js.html
function jsonObject()
{
};
var phoneListObject = new jsonObject();
function SaveJsonObject()
{
phoneListObject.Control = new jsonObject();
phoneListObject.Control.CustomerId = $("#CustomerId").val();
phoneListObject.Control.CustomerName = $("#CustomerName").val();
phoneListObject.ListBody.PhonesBlock = new jsonObject();
phoneListObject.ListBody.PhonesBlock.Phone = new Array();
$('#PhonesBlock .Phone').each(function(myindex)
{
phoneListObject.ListBody.PhonesBlock.Phone[myindex].PhoneNumber = $(".PhoneNumber input", this).val();
phoneListObject.ListBody.PhonesBlock.Phone[myindex].PhoneName = $(".PhoneName input", this).val();
});
};
$(function()
{
function SaveCurrentList()
{
SaveJsonObject();
var currentSet = phoneListObject;
var formData = { FormData: currentSet };
phoneListJSON = JSON.stringify(formData);
var FormData = "{ FormData:" + JSON.stringify(phoneListJSON) + "}";
SavePhoneListData(FormData);
};
function SavePhoneListData(phonesData)
{
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
data: phonesData,
dataFilter: function(data)
{
var msg;
if ((typeof (JSON) !== 'undefined') &&
(typeof (JSON.parse) === 'function'))
msg = JSON.parse(data);
else
msg = eval('(' + data + ')');
if (msg.hasOwnProperty('d'))
return msg.d;
else
return msg;
},
url: "../../WebServices/ManagePhones.asmx/SaveJson",
success: function(msg)
{
SaveSuccess(msg);/* the JSON is in the msg, create this function to do what you want with it. */
},
complete: function(xhr, textresponse)
{
var err = eval("(" + xhr.responseText + ")");
},
error: function(msg)
{
},
failure: function(msg)
{
}
});
};
$('#btnSave').click(function()
{
SaveCurrentList();
});
});
/* json data snip */
{"FormData":{"Control":{"CustomerId":"12345y6","CustomerName":"Joe Customer"},"PhonesBlock":{"Phone":[{"PhoneNumber":"234-233-2322","PhoneName":"son harry"},{"PhoneNumber":"234-233-2323","PhoneName":"son frank"},{"PhoneNumber":"234-233-2320","PhoneName":"momk"}]}}}
/*XML of the form data:*/
<FormData>
<Control>
<CustomerId>12345y6</CustomerId>
<CustomerName>Joe Customer</CustomerName>
</Control>
<PhonesBlock>
<Phone>
<PhoneNumber>234-233-2322</PhoneNumber>
<PhoneName>son harry</PhoneName>
</Phone>
<Phone>
<PhoneNumber>234-233-2323</PhoneNumber>
<PhoneName>son frank</PhoneName>
</Phone>
<Phone>
<PhoneNumber>234-233-2321</PhoneNumber>
<PhoneName>momk</PhoneName>
</Phone>
</PhonesBlock>
</FormData>
/* form layout snip */
<div class="control">
<div class="customer">
<input typeof="text" id="CutomerId" />
<input typeof="text" id="CutomerName" />
</div>
<div class="phoneslist" id="PhonesBlock">
<div class="Phone">
<input typeof="text" class="PhoneNumber" />
<input typeof="text" class="PhoneName" />
</div>
<div class="Phone">
<input typeof="text" class="PhoneNumber" />
<input typeof="text" class="PhoneName" />
</div>
<div class="Phone">
<input typeof="text" class="PhoneNumber" />
<input typeof="text" class="PhoneName" />
</div>
</div>
</div>
<input id="buttonSave" class="myButton" type="button" value="Save" />
signature of the web service method:
[WebMethod(EnableSession = true)]
public string SaveJson(string FormData)
{
}
Make sure your service class has [ScriptService] attribute. This attribute is not added by default.

Categories

Resources