Me and ASMX web services do not get on. We argue. She brings up arguments we had in the past. It's a pain. Our relationship is on the rocks!
I have an ASMX web service, which I haven't serialised with the Newtonsoft library (as explained why here: http://encosia.com/2011/04/13/asp-net-web-services-mistake-manual-json-serialization/). It looks like this:
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public string[] GetCitiesWithState(string isoalpha2, string prefixText)
{
var dict = AtomicCore.CityObject.GetCitiesInCountryWithStateAutocomplete(isoalpha2, prefixText);
开发者_StackOverflow社区string[] cities = dict.Values.ToArray();
return cities;
}
Simple enough right? It return this when searching for new
:
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/">
<string>New Orleans, Louisiana</string>
<string>New York, New York</string>
</ArrayOfString>
I was expecting JSON, but after a bit of reading, it seems I shouldn't try and serialise the output - it should just happen right? Anyway, so I have the following JQuery on the frontend:
$('#<%=txtCity.ClientID%>').autocomplete('<%=ResolveUrl("~/AtomicService/Assets.asmx/GetCitiesWithState")%>', {
dataType: 'json',
httpMethod: 'POST',
contentType: 'application/json; charset=utf-8',
parse: function (data) {
var rows = new Array();
for (var i = 0; i < data.d.length; i++) {
rows[i] = { data: data.d[i], value: data.d[i].Value, result: data.d[i].Value };
}
return rows;
},
formatItem: function (row, i, n) {
return row.Value;
},
extraParams: {
minChars: 2,
isoalpha2: '<%=Session["BusinessCountry"].ToString()%>',
maxRows: 20,
prefixText: function () {
return $('#<%=txtCity.ClientID%>').val()
}
},
max: 20
}).result(function (event, data, formatted) {
if (data) {
alert(data['Key']);
}
});
I can see the calls using Chrome:
And yet stuff all happens! There is no Jquery errors, no fireworks, no anything. She is ignoring me.
At first I was blaming the webservice, but I think this may have more to do with how I'm parsing and formatting the data in jquery.
So, my question is, what am I doing wrong and how can I make the autocomplete work correctly?
Help appreciated :)
EDIT: It may not be helpful, but this is what I see in Fiddler:
The jQuery UI autocomplete does not anymore use the formatItem method. That and many other such methods were present in autocomplete's earlier version that was a plugin here
I have rewritten your code using the jQuery UI's autocomplete and it works for me with the below htm and asmx files.
Refer to the demos on the jQueryUI autocomplete for more methods you could use.
I have used the json2.min.js from www.json.org Also I have added the [System.Web.Script.Services.ScriptService] attribute to the Service1 class so that it could directly be invoked from jQuery as a json web service.
These articles helped me:
ASMX and JSON – Common mistakes and misconceptions
Using jQuery to Consume ASP.NET JSON Web Services
3 mistakes to avoid when using jQuery with ASP.NET AJAX
The htm file
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>jQuery to ASMX</title>
<link rel="Stylesheet" type="text/css"
href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.11/themes/cupertino/jquery-ui.css"/>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script>
<script type="text/javascript"
src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.11/jquery-ui.min.js"></script>
<script type="text/javascript" src="http://localhost/Scripts/json2.min.js"></script>
</head>
<body>
<script type="text/javascript">
$(document).ready(function() {
$("#txtInput").autocomplete({
source:function (request, response) {
var paramters = {
isoalpha2: '<%=Session["BusinessCountry"].ToString()%>',
prefixText: request.term
};
$.ajax({
url: 'Service1.asmx/GetCitiesWithState',
type: 'POST',
dataType: 'json',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify(paramters),
success: function(data) {
response($.each(data.d, function(index, value) {
return {
label: value,
value: index
}
}));
}
});
},
minLength:2,
delay:500
});
});
</script>
<p>
Hello, World!</p>
<label for="txtInput">
Enter the string here:</label><input type="text" id="txtInput"/>
</body>
</html>
The asmx file
using System.Web.Script.Services;
using System.Web.Services;
namespace jQueryAutoCompleteBackEnd
{
/// <summary>
/// Summary description for Service1
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
[ScriptService]
public class Service1 : WebService
{
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public string[] GetCitiesWithState(string isoalpha2, string prefixText)
{
return new string[] { "New Orleans, Lousiana", "New York, New York" };
}
}
}
The reason that the asmx webmethod is returning XML rather than JSON is because the HTTP method is GET rather than POST.
In order for the autocomplete plugin to use POST you'll have to implement the source parameter using a callback function, see here
精彩评论