3

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);
        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:

what one can see in 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:

enter image description here

John Saunders
  • 160,644
  • 26
  • 247
  • 397
dooburt
  • 3,010
  • 10
  • 41
  • 59
  • Which version of autocomplete plugin are you using? The plugin that got absorbed into jQueryUI is not suppored anymore (http://bassistance.de/jquery-plugins/jquery-plugin-autocomplete/) – Hari Pachuveetil Apr 14 '11 at 15:17
  • You have dataType as JSON when the web service response is XML. – 300 baud Apr 14 '11 at 15:41
  • @Floyd Pink, I'm using the standard jquery ui one? @300 baud, I'll change it, see what that takes me... :) – dooburt Apr 14 '11 at 16:03
  • @300 baud, I changed the dataType and contentType to XML; no luck :( – dooburt Apr 14 '11 at 16:10
  • Also, in your fiddler screenshot you are calling your web service with a GET, but your jQuery code has `httpMethod: 'POST'`. – 300 baud Apr 14 '11 at 17:21

2 Answers2

5

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" };
        }

    }
}
Hari Pachuveetil
  • 10,294
  • 3
  • 45
  • 68
  • +1 just for your effort in answering. I will see if this is the answer and come back. Thanks so much however :) – dooburt Apr 15 '11 at 08:39
  • superb answer. This also lead me back to other areas I had used autocomplete and changed them to the newer version too. Thanks very much :) – dooburt Apr 16 '11 at 11:56
  • Thank you and dooburt for the question and solution, I found this very helpful. Although, I didn't include the `[ScriptMethod(ResponseFormat = ResponseFormat.Json)]` and that seems to have worked just fine. – Emmanuel F Sep 14 '11 at 16:12
0

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

Community
  • 1
  • 1
Variant
  • 17,279
  • 4
  • 40
  • 65