Im having some real problems getting JQuery autocomplete to work in Net Core.
here is my client side script :
<script>
$(document).ready(function () {
$('#txtSystemUserDisplayName').autocomplete({
change: function (event, ui) {
if (!ui.item) {
$('#txtSystemUserDisplayName').val("");
}
},
source: function (request, response) {
$.ajax({
url: "#(Url.Action("SearchEmployeesAJAX", "Home" ))",
// data: "{ 'term': '" + request.term.replace(/'/gi, "\\'") + "'}",
data: { term: 'fumanchu' },
dataType: "json", type: "POST",
contentType: "application/json; charset=utf-8",
success: function (data) {
var x = Array.prototype.slice.call(data);
response($.map(x, function (item) {
return {
label: item.employeeDisplayName,
}
}))
}, error: function (response) { alert(response.responseText); }, failure: function (response) { alert(response.responseText); }
});
},
select: function (e, i) {
$("#hfSystemUserDisplayName").val(i.item.label);
},
minLength: 1
});
});
Now when i start typing , the autocomplete fires but the param in the controller method is NULL , no matter what i do. it doesnt matter what i call the 'term' in the data object of the request. And yes i am making sure that the controller method parameter is named the same . eg
public JsonResult SearchEmployeesAJAX(String term) {
as you can see ive even commented it out and hardcoded a string in there, still null.
it DOES work if I set the string as part of the URL eg:
url: "#(Url.Action("SearchEmployeesAJAX", "Home", new {#term="blahblahblah" }
This is how I have always done autocompletes in the past on .Net Framework, and never had an issue. Is there something different about Net Core that im not aware of, maybe something different about how requests are formed?
Any help would be appreciated.
Ok so if anyone else is also having this problem, it appears that you cant use the Url.Action helper anymore and still have the parameter not be null.
You will need to use a raw string as the url instead, which seemed to solve this.
Related
I'm having a little problem understanding Cypress documentation. In the alias section they've added a use case of accessing alias with fixtures using the this.* reference:
beforeEach(() => {
// alias the users fixtures
cy.fixture("users.json").as("users");
});
it("utilize users in some way", function () {
// access the users property
const user = this.users[0];
// make sure the header contains the first
// user's name
cy.get("header").should("contain", user.name);
});
But when I try to reproduce it, I keep getting the error: Cannot read property 'SOAP_body' of undefined.
I don't understand where is my error. Here is my spec:
/// <reference types="cypress"/>
describe("SOAP API Test", () => {
beforeEach(() => {
cy.fixture("SOAP_body.xml").as("SOAP_body");
});
it("Test with task", function () {
const body = this.SOAP_body;
cy.request({
method: "POST",
headers: {
"content-type": "text/xml; charset=utf-8",
Authorization: "Token myVerySecretToken",
SOAPAction: "http://tempuri.org/TrackingFull",
},
url: `https://path.of/the/application.asmx`,
body: body,
failOnStatusCode: false,
}).then((result) => {
expect(result.status).to.equal(200);
cy.task("XMLtoJSON", result.body).then((response) => {
expect(
response.elements[0].elements[1].elements[0].elements[0]
.elements[1].elements[0].elements[0].elements[0]
.elements[0].elements[0].text
).to.equal("something");
});
});
});
});
and my task
/**
* #type {Cypress.PluginConfig}
*/
module.exports = (on, config) => {
on("task", {
XMLtoJSON(XML_body) {
var convert = require("xml-js");
let result = convert.xml2js(XML_body, {
compact: false,
spaces: 2,
});
return result;
},
});
};
Using debugger just before the const definition I can see that the variables are undefined
I do know about cy.get(), but I just wanted to learn how to use the this.* pattern.
After fiddling with the code I've realized that I was using an arrow function in the step definition:
it("Test with task", () => { ... }
I've done it simply because I use a lot of code snippets in VSC, and never paid attention to the syntax is used.
So, after seeing it, I've remembered that it would never work, as the MDN documentation says:
An arrow function expression is a compact alternative to a traditional
function expression, but is limited and can't be used in all
situations.
Differences & Limitations:
Does not have its own bindings to this or super, and should not be used as methods.
Does not have arguments, or new.target keywords.
Not suitable for call, apply and bind methods, which generally rely on establishing a scope.
Can not be used as constructors.
Can not use yield, within its body.
The solution was simple as replacing it with a function definition:
it("Test with task", function () { ... }
and the this context was as expected
Moral of the history, don't trust blindly in your code editor (even if its VSC)
I'm not able to pass a double to my action (at least not in a proper way).
This is my action:
public JsonResult SomeAction(double? n = null)
{
// ...
}
And this is my ajax call:
$.ajax({
async: true,
type: 'POST',
url: '/SomeController/SomeAction',
data: {
"n": 1.5
},
success: function (data) {
...
}
});
The number 1.5 is not being passed to the action. When debugging in serverside, I'm receiving a null instead.
If I change the ajax to this:
$.ajax({
async: true,
type: 'POST',
url: '/SomeController/SomeAction',
data: {
"n": "1,5"
},
success: function (data) {
...
}
});
I do get a 1.5 in serverside.
What change in serverside do I need to do so that the first ajax call works?
Another thing that worked for me was using the first ajax call and changing the signature of the action to this:
public JsonResult SomeAction(string n = "")
{
double parsedN = Convert.ToDouble(n);
}
Of course both solutions suck
What finally worked was the answer of this other question:
ASP.NET MVC Form and double fields
Quoting here:
Might be caused by cultureinfo, some culture use , instead of . for
decimal separator. try setting the following in web.config,
<system.web>
<globalization culture="en-US" uiCulture="en-US" />
</system.web>
I am using Blueimp fileupload() to post image files to a django-tastypie API.
The code below works correctly as far as the file is being uploaded:
$("#image").fileupload({
dataType: 'json',
start: function() {
console.log("start fileupload");
},
progress: function(e, data) {
console.log(data.loaded + " " + data.total);
},
beforeSend: function(xhr, settings) {
xhr.setRequestHeader("X-CSRFToken", $.cookie('csrftoken'));
},
done: function(e, data) {
console.log("done uploading file.");
}
});
$("#image").bind('fileuploadfinished', function (e, data) {
console.log("fileuploadfinished");
});
However, the done callback is never called. I tried binding the fileuploadfinished and that is also never called.
start and progress are both called as expected.
beforeSend is undocumented, but is needed by django-tastypie for SessionAuthentication - removing it doesn't change that done and fileuploadfinished is never called.
As it turns out, django-tastypie correctly returns a 201 status code. However, this status code is not considered a success by fileupload.
This code handles the status code manually:
$("#image").fileupload({
dataType: 'json',
beforeSend: function(xhr, settings) {
xhr.setRequestHeader("X-CSRFToken", $.cookie('csrftoken'));
},
complete: function(xhr) {
if (xhr.readyState == 4) {
if (xhr.status == 201) {
console.log("Created");
}
} else {
console.log("NoGood");
}
},
});
That means, the complete callback is called whether success or failure, and checking the readyState and status together can tell whether it succeeded.
There are some other ways to get this to work, however I think this is the best. More details here:
Data inserted successful but jquery still returning error
I was having the same problem. it is because you set your datatype 'json'.
Just leave this out or put it to plain and it will work.
Your server , or uploadhandler isn't return a json answer.
I have the following code which does not post data as expected
var casper = require('casper').create();
var myData;
var utils = require('utils');
casper.start();
casper.then(function () {
myData = {"source":"casperjs"};
utils.dump(myData);
});
casper.thenOpen('http://my-api/api/upload/', {
method: "post",
data: JSON.stringify(myData),
headers: {
"Content-Type":"application/json"
}
}, function () {
utils.dump(myData);
});
casper.run();
The message was sent to my server but without valid data. However, if I move the thenOpen(...) into the then(...) like this
casper.then(function () {
myData = {"source":"casperjs"};
utils.dump(myData);
this.thenOpen('http://my-api/api/upload/', {
method: "post",
data: JSON.stringify(myData),
headers: {
"Content-Type":"application/json"
}
}, function () {
utils.dump(myData);
});
});
Then the post would succeed. Or If i change the thenOpen part in the original code (i.e., without moving it in to the casper.then(...) part, like this
casper.thenOpen('http://my-api/api/upload/', {
method: "post",
data: JSON.stringify({"source":"casperjs"}),
headers: {
"Content-Type":"application/json"
}
}, function () {
utils.dump(myData);
});
Then the post would also be successful. So it looks like myData has to be initialized when the thenOpen(...) is seen. So is this expected or I have done something wrong? I could not find reference about this behavior. Thanks!
This is expected behavior as casperjs schedules the steps before running them. This means for your first listing that JSON.stringify(undefinded) will be sent to the server. The reason is that your first casper.then block was not yet executed when the object is evaluated for your casper.thenOpen block. Therefore your data was not yet assigned properly to myData, which happens inside the step.
The evaluation of the POST data on the other hand is done for the thenOpen call and not inside, so it is executed synchronously.
You already provided some good alternatives.
I have gone through as many questions on here as I could find and tried all the different suggestions and cannot get this to work. I have a view that is bound with Knockout using the mapping plugin and it works okay but only when I do the "wrong thing". Everything that I have read says that you should only make one call to ko.applyBindings() per view and then everything should update using ko.mapping.fromJS(). I cannot seem to get this to work, the only way I have been able to get my view to refresh is to call ko.applyBindings() again in the success call back from my .ajax() call. Here is the offending code.
<script type="text/javascript">
var viewModel;
$(document).ready(function() {
$("#panelbar").kendoPanelBar({
expandMode: "multiple"
});
$.ajax({
type: 'GET',
url: '/Home/IsUserMarketingManager',
success: function (data) {
if (data == true) {
$('#submitNewCase').hide();
$('#approveCase').show();
$('#disapproveCase').show();
}
}
});
// Generate client View Model from Server View Model
viewModel = new ViewModel();
ko.mapping.fromJS(#Html.Raw(Json.Encode(Model)),{}, viewModel);
ko.applyBindings(viewModel);
});
function ViewModel () {
var self = this;
self.addLocation = function() {
self.AdditionalLocations.push({ GaNumber: "" });
};
}
</script>
And later this to update the form with retrieved data:
<script type="text/javascript">
$('#btnImport').click(function () {
$.blockUI({ message: '<h2>Importing Client Information...</h2> <img src="/Images/ajax-loader.gif"><br />' });
$.ajax({
type: 'post',
url: '/Home/ImportClientCrmInfoJson',
dataType: "json",
data: ko.mapping.toJS(viewModel),
success: function (data) {
$.unblockUI();
if (!data.AccountNull) {
ko.mapping.fromJS(data, {}, viewModel);
} else {
alert("Could not find account for this GA Number, please try again.");
}
}
});
});
</script>
When submitting the form to my controller, all the data is there and mapped correctly to my server side View Model, but the form in the view isn't updated with the data that comes back from the $.ajax call. I've gotten the form to update if I do the following, but I know it's not the right way and has caused me other issues as well.
<script type="text/javascript">
$('#btnImport').click(function () {
$.blockUI({ message: '<h2>Importing Client Information...</h2> <img src="/Images/ajax-loader.gif"><br />' });
$.ajax({
type: 'post',
url: '/Home/ImportClientCrmInfoJson',
dataType: "json",
data: ko.mapping.toJS(viewModel),
success: function (data) {
$.unblockUI();
if (!data.AccountNull) {
viewModel = ko.mapping.fromJS(data);
ko.applyBindings(viewModel); // This works but isn't the right way...
} else {
alert("Could not find account for this GA Number, please try again.");
}
}
});
});
</script>
Any help would be much appreciated.
Have you examined that the following line of code appears to create a 'NEW' viewmodel?
viewModel = ko.mapping.fromJS(data);
When you do this the new viewModel the old bindings are destroyed. This is why you have to call ApplyBindings again. Anyway, I think the above line of code is the root of the problem.
Is there a way for you to create an observable property on the viewModel and allow the viewModel to reflect the data in this object? That may be a more practical approach to the update process.
In the success callback of the ajax call, use this method ko.applyBindings(viewModel) but pass as a second parameter the DOM portion you want to update as follows
ko.applyBindings(viewModel, $("#mydiv")[0])
Don't use a jquery object but a REAL DOM object.