0

I am currently working with a c# asp.net usercontrol in which I need a functional autocomplete.

The script looks like it wants to run, as you can see; the progress bar spins, but it ALWAYS comes back 'Error'. I'm not sure what to do from here. I followed at least 5 different tutorials to get this working; the code mimics the code found here; but it doesn't seem to work when all is said and done. What am I missing? Any suggestions to get me where I need to be would be much appreciated.

If any more information is needed let me know, but the entire code can be found below.

enter image description here

HTML/Javascript

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="Search Textbox.ascx.cs" Inherits="StagingApplication.Search.Search_Textbox" %>

<link href="../css/styleCustomPages.css" rel="stylesheet" />
<link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.1/themes/base/jquery-ui.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.1/jquery-ui.min.js"></script> 
<script type="text/javascript">
    $(document).ready(function () {
        SearchText();
    });
    function SearchText() {
            $(".autosuggest").autocomplete({
                source: function (request, response) {
                    $.ajax({
                        type: "POST",
                        contentType: "application/json; charset=utf-8",
                        url: "Search_Textbox.aspx/GetAutoCompleteData",
                        data: "{'searchText':'" + document.getElementById('txtSearch').value + "'}",
                        dataType: "json",
                        success: function (data) {
                            response(data.d);
                        },
                        error: function (result) {
                            alert('Error' );
                        }
                    });
                }
            });
    }
</script>

<div class="ui-widget">
<label for="tbAuto">Enter UserName: </label>
<input type="text" id="txtSearch" class="autosuggest" />
</div>

C# Code Behind

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
using System.Data.SqlClient;
using System.Web.Services;
using System.Web.Script.Services;

namespace StagingApplication.Search
{
    public partial class Search_Textbox : System.Web.UI.UserControl
    {
        #region Declarations
        static string dbSearch = "db string";
        #endregion

        protected void Page_Load(object sender, EventArgs e)
        { }

        #region Methods and Functions
        [WebMethod, ScriptMethod]
        public static List<string> GetAutoCompleteData(string searchText)
        {
            List<string> result = new List<string>();
            using (SqlConnection con = new SqlConnection(dbSearch))
            {
                using (SqlCommand cmd = new SqlCommand("SELECT TOP 1000 [SearchTerm] FROM [Search].[dbo].[Cache] where AutoCompleteTerm = 0 and SearchTerm LIKE @SearchText + '%';", con))
                {
                    con.Open();
                    cmd.Parameters.AddWithValue("@SearchText", searchText);
                    SqlDataReader dr = cmd.ExecuteReader();
                    while (dr.Read())
                    {
                        result.Add(dr["SearchTerm"].ToString());
                    }
                    return result;
                }
            }
        }
    }
}
Stephen Kennedy
  • 20,585
  • 22
  • 95
  • 108
Volearix
  • 1,573
  • 3
  • 23
  • 49
  • What is the actual error you're getting? – entropic Oct 27 '14 at 15:19
  • @entropic That's part of the issue. I'm not a javascripter and I'm not quite sure how to get the equivalent of c#'s `ex.ToString()` to output the error message. – Volearix Oct 27 '14 at 15:21
  • If you change your error function to: `error: function (xhr, msg, e) { alert(JSON.parse(xhr.responseText).Message); }` .. what do you see? – entropic Oct 27 '14 at 15:23
  • @entropic Nothing happens at all with that code. – Volearix Oct 27 '14 at 15:25
  • is your dbSearch equal to a connection string instead of "db string" in your code? – jiy Oct 27 '14 at 15:26
  • @entropic if I use `error: function (xhr, msg, e) {alert(msg.Message); }` it returns 'Undefined' and that's it. – Volearix Oct 27 '14 at 15:26
  • Put a break point at your alert, and inspect what `result` or anything else you're passing to the error function. We need more information than just "Error keeps popping up" – entropic Oct 27 '14 at 15:27
  • @jiy yep. And the code there works because I tried it as just a 'click event' – Volearix Oct 27 '14 at 15:27
  • I believe that the `Post` portion is not working. The data returned is `Undefined` so it leads me to believe it isn't finding the web method. This is an `.ascx` control so am I even able to use this method? – Volearix Oct 27 '14 at 15:31
  • So does the url `Search_Textbox.aspx/GetAutoCompleteData` exist? – entropic Oct 27 '14 at 15:45
  • @entropic I don't think it's found, no. I think that is the root of the problem, but every path I've tried does nothing. – Volearix Oct 27 '14 at 15:47
  • You said it's a user control correct? Those don't have pages for themselves - they have to be placed into a page. If you want this to be a user control, you should create a separate page dedicated to making the service calls that will resolve to an actual URL. (Similarly, if you take the WebMethod out and put it in the actual ASPX page, what happens?) – entropic Oct 27 '14 at 15:49
  • @entropic So, basically saying that this method will NOT work, correct? I'm trying to see because I feel like I'm wasting my time here a bit. – Volearix Oct 27 '14 at 15:57
  • I'm saying the method wouldn't work in a User Control - if you were to put it in a page I'm pretty sure it would be fine. – entropic Oct 27 '14 at 16:13
  • @entropic Okay, unfortunately it HAS to be a user control due to the nature of my companies architecture. I'll just have to find an alternative approach. :/ – Volearix Oct 27 '14 at 17:26

3 Answers3

0
cmd.Parameters.AddWithValue("@SearchText", searchText);

Variable searchText doesn't exist, because:

Your function begins with this:

public static List<string> GetAutoCompleteData(string username)

It should be:

public static List<string> GetAutoCompleteData(string searchText)

You forgot to update username to searchText.

  • That didn't change anything. The `'Error'` alert is still there. – Volearix Oct 27 '14 at 15:16
  • Well it definitely needed to be fixed. Have you tried removing ScriptMethod? I don't do AJAX very much, but I'm sure that's for GET and you're doing a POST. – Nathan Surfus Oct 27 '14 at 15:33
  • Tried removing it to no avail. Still fails. – Volearix Oct 27 '14 at 15:38
  • What's the contents of the file: Search_Textbox.aspx – Nathan Surfus Oct 27 '14 at 15:42
  • <%@ Page Language="C#" AutoEventWireup="true" MasterPageFile="~/Site.Master" CodeBehind="Search Textbox.aspx.cs" Inherits="StagingApplication.Search.Search_Textbox" %> <%@ Register Src="~/Search/Search Textbox.ascx" TagPrefix="uc1" TagName="SearchTextbox" %> – Volearix Oct 27 '14 at 15:44
0

In the aspx page, you need to declare a WebMethod which will call the code in the user control. This is how I do it in one of our sites:

[WebMethod]
public static WebMethodReturn<IEnumerable> GetWatchboxes()
{
    return AddOns_WatchboxAdmin.GetWatchboxes();
}

...making sure in jQuery to call the page method url of the aspx page not the control.

My answer here may help a little bit too, particularly the recommendation to debug web traffic with Fiddler.

Its important to note that your "Error" string is in the jQuery error block. That means it's probably a transport error or some sort of error in jQuery. My guess is 404 because you don't have a page method in the aspx page only in the user control. This error block won't catch server side exceptions. I return a little wrapper class with a Data property and an Error property; I put any exception string into the Error property otherwise I leave it null. I check this string clientside. This is optional, just a little tip that jQuery knows nothing about .NET exceptions - not that I believe an exception is the problem here.

The ScriptMethod attribute is needed in ASMX web services in order to return JSON but for reasons unknown to me you don't need it in page methods.

You certainly do not need to be doing any manual serialisation to JSON as instructed in another answer. If called correctly by jQuery, the example I have given will return JSON with no further work needed.

So, to summarise, put this into your aspx.cs:

[WebMethod]
public static List<string> GetAutoCompleteData(string searchText)
{

and call and return the results of the same function in the instance of the user control on your aspx page (or make the function public static in the user control). Inspect the client call and server response in Fiddler in case of any problems.

Community
  • 1
  • 1
Stephen Kennedy
  • 20,585
  • 22
  • 95
  • 108
-1

Since you're expecting JSON to be returned, you may need to try something like this:

Add the following declaration:

using System.Web.Script.Serialization;

Then perform the following on your List<string> result variable:

JavaScriptSerializer serializer = new JavaScriptSerializer();
serializer.MaxJsonLength = Int32.MaxValue; // optional
return serializer.Serialize(result);

UPDATE - here's a more complete solution for outputting your data to JSON:

public static string GetDataTableToJSONString(DataTable table) {
    List<Dictionary<string, object>> list = new List<Dictionary<string, object>>();
    foreach (DataRow row in table.Rows) {
        Dictionary<string, object> dict = new Dictionary<string, object>();
        foreach (DataColumn col in table.Columns) {
            dict[col.ColumnName] = row[col];
        }
        list.Add(dict);
    }
    JavaScriptSerializer serializer = new JavaScriptSerializer();
    serializer.MaxJsonLength = Int32.MaxValue;
    return serializer.Serialize(list);
}

public static List<string> GetAutoCompleteData(string searchText) {
    string sql = "SELECT TOP 1000 [SearchTerm] FROM [Search].[dbo].[Cache] " +
        "where AutoCompleteTerm = 0 and SearchTerm LIKE @SearchText + '%';";
    using (SqlConnection con = new SqlConnection(dbSearch)) {
        con.Open();
        using (SqlCommand cmd = new SqlCommand(sql, con)) {
            cmd.Parameters.AddWithValue("@SearchText", searchText);
            using (SqlDataAdapter da = new SqlDataAdapter(cmd)) {
                using (DataSet ds = new DataSet()) {
                    da.Fill(ds);
                    return GetDataTableToJSONString(ds.Tables[0]);
                }
            }
        }
    }
}
jiy
  • 858
  • 2
  • 9
  • 18