问题
What is the best method to troubleshooting a jQuery AJAX call with ASP.NET? The error function is getting called--I get the alert to popup that says "Error", but I don't know why. When I attach to my process (w3wp.exe), and place a breakpoint into the code behind of my generic handler ProcessRequest method, it doesn't stop there. So it's not even reaching the handler. Why would that be?
It's also only executing the error function every other click on my search button (BtnUCSSearch). And I don't have an option to press okay on the Error popup like a typical JavaScript alert. It flickers and goes away. I tried putting in a return false to prevent a full page postback, but that didn't seem to work.
Requesting Page JavaScript:
jQuery("#<%=BtnUCSSearch.ClientID %>").click(function() {
urlToHandler = '/Accessioning/FullDataEntry/AddressSearch.ashx';
// hard coding input values for now
jsonData = '{ "CompanyName":"xxx", "PrimaryPhone":"555-555-5555", "PostalCode":"55555" }';
jQuery.ajax({
url: urlToHandler,
data: jsonData,
dataType: 'json',
type: 'POST',
contentType: 'application/json',
success: function(data) {
alert(data.UCSAddress);
},
error: function(data, status, jqXHR) {
alert('Error');
}
}); // end jQuery.ajax
});
Response Page for AJAX call code behind (AddressSearch.ashx.vb):
Imports System
Imports System.Web
Imports System.Web.Services
Imports System.Web.HttpContext
<WebService([Namespace]:="http://tempuri.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
Public Class AddressSearch
Implements System.Web.IHttpHandler
Implements System.Web.SessionState.IReadOnlySessionState
ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
Get
Return False
End Get
End Property
Public Sub ProcessRequest(ByVal context As HttpContext) Implements System.Web.IHttpHandler.ProcessRequest
context.Response.ContentType = "application/json"
Dim companyName As String = DirectCast(HttpContext.Current.Request.Form("CompanyName"), String)
Dim primaryPhone As String = DirectCast(HttpContext.Current.Request.Form("PrimaryPhone"), String)
Dim postalCode As String = DirectCast(HttpContext.Current.Request.Form("PostalCode"), String)
Dim json As String = "{ ""UCSAddress"": ""xxxxxxxxx"" }"
context.Response.Write(json)
End Sub
End Class
=============================
1/2/2012 @ 12:49pm update
Per the two answers, I did a little bit more troubleshooting..
The way I was retrieving the query string parameters didn't seem to work by using Form. So I'm now using QueryString instead. The page was still returning the JSON object correctly. But at least my query string parameters should work now. However, in this exercise, I explicitly called my generic handler directly from the browser--not via my jQuery.ajax call. So I know the page works well now.
https://localhost/Accessioning/FullDataEntry/AddressSearch.ashx?CompanyName=xxx&PrimaryPhone=555-555-5555&PostalCode=55555
Response:
{ "responseProperty": "xxxxxxxxx" }
Note, I did both methods.. even the approach Mr. Duarte suggested (JavaScriptSerializer). They both work the same.. just a little bit different architecture. Notice I had to create a custom class called SimpleResponse.
Public Sub ProcessRequest(ByVal context As HttpContext) Implements System.Web.IHttpHandler.ProcessRequest
' architecture #1 without JavaScriptSerializer (works)
context.Response.ContentType = "application/json"
Dim companyName As String = DirectCast(HttpContext.Current.Request.QueryString("CompanyName"), String)
Dim primaryPhone As String = DirectCast(HttpContext.Current.Request.QueryString("PrimaryPhone"), String)
Dim postalCode As String = DirectCast(HttpContext.Current.Request.QueryString("PostalCode"), String)
Dim json As String = "{ ""responseProperty"": ""xxxxxxxxx"" }"
context.Response.Write(json)
' architecture #2 with JavaScriptSerializer and SimpleResponse class (also works)
'context.Response.ContentType = "application/json"
'Dim json As JavaScriptSerializer = New JavaScriptSerializer()
'context.Response.Write(json.Serialize(New SimpleResponse()))
'http://codereview.stackexchange.com/questions/3208/basic-simple-asp-net-jquery-json-example
End Sub
Public Class SimpleResponse
Public Property responseProperty() As String
Get
Return _responseProperty
End Get
Set(ByVal value As String)
_responseProperty = value
End Set
End Property
Private _responseProperty As String
Public Sub New()
_responseProperty = "reponse via SimpleResponse class"
End Sub
End Class
================
I also tried wrapping my jsonData with JSON.stringify.. I'm still getting the error. Originally, the jQuery wasn't even calling the page because the class name on the handler had a "1" at the end. When I created the generic handler, it appended a "1" because I already had a page and code behind class named AddressSearch.aspx. I've since fixed that. I had to search for "AddressSearch1" because I couldn't directly edit the file by double clicking it in Solution Explorer.
<%@ WebHandler Language="VB" CodeBehind="AddressSearch.ashx.vb" Class="UI.Web.AddressSearch1" %>
================
Now it's at least calling my code behind, but it's not passing the query string parameters with the data I set in jsonData (that I also stringify'ed). It's also still throwing the errors.
Also put "var" in front of my JS variables.
We're getting closer.
jQuery("#<%=BtnUCSSearch.ClientID %>").click(function() {
var urlToHandler = 'AddressSearch.ashx';
//var urlToHandler = '~/Accessioning/FullDataEntry/AddressSearch.ashx';
//urlToHandler = '/Accessioning/FullDataEntry/AddressSearch.ashx';
// hard coding input values for now
var jsonData = '{ CompanyName:"xxx", PrimaryPhone:"555-555-5555", PostalCode:"55555" }';
//var jsonData = [{ CompanyName: "xxx", PrimaryPhone: "555-555-5555", PostalCode: "55555"}];
jQuery.ajax({
url: urlToHandler,
data: JSON.stringify(jsonData),
dataType: 'json',
type: 'POST',
contentType: 'application/json',
success: function(data) {
//alert("got here");
alert(data.responseProperty);
console.log(" .. response :" + data);
return false;
},
error: function(data, status, jqXHR) {
alert('Error');
//console.log("error :" + XMLHttpRequest.responseText);
//console.log(" .. error :" + data.responseText);
console.log(" .. error");
return false;
}
});
});
==========================
1/2/2012 @ 1:52pm
code snippet #1 (GET request):
jQuery("#<%=BtnUCSSearch.ClientID %>").click(function() {
jQuery.get("AddressSearch.ashx", { CompanyName: "xxx", PrimaryPhone: "555", PostalCode: "55555" }, function(data) {
alert("got here");
//alert("Data Loaded: " + data.responseProperty);
return false;
});
});
calling page via request page (for #1):
params: http://screencast.com/t/oA0i48O5y7
headers: http://screencast.com/t/3khfRjI7
response: nothing
calling page via browser directly (for #1): https://localhost/Accessioning/FullDataEntry/AddressSearch.ashx?CompanyName=xxx&PrimaryPhone=555&PostalCode=55555 response (page output) although console says nothing: {"responseProperty":"reponse via SimpleResponse class"}
=====================
code snippet #2 (POST request type):
var urlToHandler = 'AddressSearch.ashx';
var jsonData = '{ CompanyName:"xxx", PrimaryPhone:"555-555-5555", PostalCode:"55555" }';
jQuery.ajax({
url: urlToHandler,
data: JSON.stringify(jsonData),
dataType: 'json',
type: 'POST',
contentType: 'application/json',
success: function(data) {
if (data != null) {
alert(data.responseProperty);
console.log(" .. response :" + data);
}
return false;
},
error: function(data, status, jqXHR) {
if (data != null) {
alert("Error: " + data.responseText);
console.log(" .. error :" + data.responseText);
}
alert("error occurred");
return false;
}
});
calling page via request page (for #2):
headers: http://screencast.com/t/ostM7NKCxT
post: http://screencast.com/t/VKZdgGuOl
response: http://screencast.com/t/LP3R8OAm
calling page via browser directly (for #2): https://localhost/Accessioning/FullDataEntry/AddressSearch.ashx?CompanyName=xxx&PrimaryPhone=555&PostalCode=55555
response (page output) although console says nothing: {"responseProperty":"reponse via SimpleResponse class"}
============================
1/2/2012 @2:48pm
Final code. Notice the e.preventDefault() and this line of code to prevent that mysterious error. Both were the remaining issues: jQuery("#form").submit(function() { return false; }); Although with the e.preventDefault() call, you don't need the other line. So I commented it out.
jQuery(document).ready(function() {
//jQuery("#form").submit(function() { return false; });
jQuery("#<%=TxtLastName.ClientID %>").focus();
//jQuery("#<%=PnlUCSSearch.ClientID %>").hide();
// START unassigned collection site address search logic
jQuery("#<%=DDLCollectionSite.ClientID %>").change(function() {
//alert("hello world: " + this.value);
if (this.value != "2") {
jQuery("#<%=PnlUCSSearch.ClientID %>").hide();
jQuery("#<%=DDLCollectionSite.ClientID %>").focus();
}
else {
jQuery("#<%=PnlUCSSearch.ClientID %>").show();
jQuery("#<%=TxtUCSCompany.ClientID %>").focus();
}
});
jQuery("#<%=BtnUCSSearch.ClientID %>").click(function(e) {
// jQuery.get("AddressSearch.ashx", { CompanyName: "xxx", PrimaryPhone: "555", PostalCode: "55555" }, function(data) {
// alert("Data Loaded: " + data.responseProperty);
// return false;
// });
var urlToHandler = 'AddressSearch.ashx';
//var urlToHandler = '~/Accessioning/FullDataEntry/AddressSearch.ashx';
//urlToHandler = '/Accessioning/FullDataEntry/AddressSearch.ashx';
// hard coding input values for now
var jsonData = '{ CompanyName:"xxx", PrimaryPhone:"555-555-5555", PostalCode:"55555" }';
//var jsonData = [{ CompanyName: "xxx", PrimaryPhone: "555-555-5555", PostalCode: "55555"}];
jQuery.ajax({
url: urlToHandler,
data: JSON.stringify(jsonData),
dataType: 'json',
type: 'POST',
contentType: 'application/json',
success: function(data) {
if (data != null) {
alert(data.responseProperty);
console.log(" .. response :" + data);
}
},
error: function(data, status, jqXHR) {
//if (data != null) {
// alert("Error: " + data.responseText);
// console.log(" .. error :" + data.responseText);
//}
//alert("error occurred");
}
});
e.preventDefault();
});
// END unassigned collection site address search logic
});
回答1:
I tried putting in a return false to prevent a full page postback, but that didn't seem to work.
If the main problem is that clicking the button control causes a full post back instead of an asynchronous call to your handler, you can add this code anywhere inside your jQuery click event handler:
jQuery("#<%=BtnUCSSearch.ClientID %>").click(function(e) {
// Existing code
e.preventDefault();
})
This works rather than return false
to stop the browser's normal behavior for the button click.
回答2:
Inspect the browsers console
for more details and set breakpoints in your callbacks (success
, error
)
回答3:
first of all, take care with global variables in javascript, if is possible abandon this pratice.
Make sure requisition URL is correct and not return 404 error.
In jquery ajax data, use JSON.stringify().
And in the asp.net handler use the JavascriptSerializer.
If not work, run with the firebug console opened, or chrome console. It's very helpful!
来源:https://stackoverflow.com/questions/8703317/troubleshooting-jquery-ajax-call-using-generic-handler-in-asp-net