web-dev-qa-db-fra.com

jQuery Autocomplete et ASP.NET

J'ai cherché partout sur ce site et sur le Web un bon et simple exemple de saisie semi-automatique en utilisant jQuery et ASP.NET. Je voulais exposer les données utilisées par la saisie semi-automatique avec un webservice (et je le ferai probablement ensuite). En attendant, je l'ai fait fonctionner, mais cela semble un peu hacky ...

Dans ma page, j'ai une zone de texte:

<input id="txtSearch" type="text" />

J'utilise la saisie semi-automatique jQuery, configurée selon leur exemple:

<link rel="stylesheet" href="js/jquery.autocomplete.css" type="text/css" />
<script type="text/javascript" src="js/jquery.bgiframe.js"></script>
<script type="text/javascript" src="js/jquery.dimensions.pack.js"></script>
<script type="text/javascript" src="js/jquery.autocomplete.js"></script>

Voici où ça commence à devenir hacky ... J'appelle une page au lieu d'un webservice:

  <script type="text/javascript">
    $(document).ready(function(){
        $("#txtSearch").autocomplete('autocompletetagdata.aspx');
    });      
  </script>

Dans la page, j'ai supprimé TOUS les fichiers html et je l'ai juste (sinon, divers bits HTML apparaissent dans la liste déroulante de saisie semi-automatique):

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="autocompletetagdata.aspx.cs" Inherits="autocompletetagdata" %>

Et dans mon autocompletetagdata.aspx, j'utilise SubSonic pour interroger, formater et renvoyer les données de la base de données (un élément de données par ligne):

protected void Page_Load(object sender, EventArgs e)
{
    // Note the query strings passed by jquery autocomplete:
    //QueryString: {q=a&limit=150&timestamp=1227198175320}

    LookupTagCollection tags = Select.AllColumnsFrom<LookupTag>()
        .Top(Request.QueryString["limit"])
        .Where(LookupTag.Columns.TagDescription).Like(Request.QueryString["q"] + "%")
        .OrderAsc(LookupTag.Columns.TagDescription)
        .ExecuteAsCollection<LookupTagCollection>();

    StringBuilder sb = new StringBuilder();

    foreach (LookupTag tag in tags)
    {
        sb.Append(tag.TagDescription).Append("\n");
    }

    Response.Write(sb.ToString());
}

Si vous ne faites pas de requête LIKE, elle renvoie tout ce qui contient une correspondance pour le (s) caractère (s) que vous tapez - par exemple, en tapant "a", "Ask" et "Answer" ainsi que "March" et "Mega." Je voulais juste qu'il commence par un match.

Quoi qu'il en soit, cela fonctionne et c'est assez facile à installer, mais y a-t-il une meilleure façon?

50
djuth

J'ai récemment implémenté la saisie semi-automatique, et cela semble assez similaire. J'utilise un ashx (Generic Handler) au lieu de l'aspx, mais c'est fondamentalement le même code dans le code derrière.

En utilisant l'ashx, cela ressemblera à ceci:

<script type="text/javascript">
  $(document).ready(function(){
      $("#txtSearch").autocomplete('autocompletetagdata.ashx');
  });      
</script>

[WebService(Namespace = "http://www.yoursite.com/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class AutocompleteTagData : IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        // Note the query strings passed by jquery autocomplete:
        //QueryString: {q=a&limit=150&timestamp=1227198175320}

        LookupTagCollection tags = Select.AllColumnsFrom<LookupTag>()
            .Top(context.Request.QueryString["limit"])
            .Where(LookupTag.Columns.TagDescription).Like(context.Request.QueryString["q"] + "%")
            .OrderAsc(LookupTag.Columns.TagDescription)
            .ExecuteAsCollection<LookupTagCollection>();

        foreach (LookupTag tag in tags)
        {
            context.Response.Write(tag.TagDescription + Environment.NewLine);
        }
    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
}
32
bdukes

Je viens de poster ceci sur une autre question, mais vous pouvez remplacer la fonction d'analyse sur le plug-in de saisie semi-automatique jQuery pour qu'elle prenne en charge n'importe quelle sortie.

Exemple:

    $("#<%= TextBox1.ClientID %>").autocomplete("/Demo/WebSvc.asmx/SuggestCustomers", {
        parse: function(data) {
            var parsed = [];

            $(data).find("string").each(function() {
                parsed[parsed.length] = {
                    data: [$(this).text()],
                    value: $(this).text(),
                    result: [$(this).text()]
                };
            });
            return parsed;
        },
        dataType: "xml"
    });

Tout cela attend est un tableau de chaînes au format XML ... Très facile à faire ... Si vous utilisez SubSonic, vous devriez vérifier le RESTHandler (c'est un GEM caché !!!), il prend en charge les requêtes de base sur tous vos objets et peut retourne JSON/XML. Voici un exemple de requête l'utilisant ...

/Demo/services/Customers/list.xml?CustomerName=JOHN

Si vous changez list.xml en list.json, les résultats seront remplacés par JSON. La demande ci-dessus renverra l'entité "Client" fortement tapée. Vous pouvez changer le paramètre pour supporter LIKE, NOT LIKE, etc ... Très puissant et toute la plomberie est déjà terminée ...

Voici une vidéo à ce sujet: http://subsonicproject.com/tips-and-tricks/webcast-using-subsonic-s-rest-handler/

10
Zachary

Le service Web ou un service WCF vous donnera le potentiel d'une meilleure interface. Les deux peuvent également être configurés pour effectuer la sérialisation Json.

Puisque je prends un cours WCF pendant que j'écris (je fais vraiment une pause!), Je vais esquisser la méthode WCF.

[OperationContract]
[WebInvoke(RequestFormat=WebMessageFormat.Json,
           ResponseFormat=WebMessageFormat.Json)]
public LookupTagCollection LookupTags( int limit, string q )
{
     return Select.AllColumnsFrom<LookupTag>()
                  .Top(limit)
                  .Where(LookupTag.Columns.TagDescription)
                  .Like(q+ "%")
                  .OrderAs(LookupTag.Columns.TagDescription)
                  .ExecuteAsCollection<LookupTagCollection>();    
}

LookupTagCollection doit être sérialisable.

6
tvanfosson

Jquery 1.8 Autocomplete utilise "term" et non "q" comme paramètre de chaîne de requête. c'est la version courte et douce que j'ai implémentée. J'espère que cela aide quelqu'un.

Javascript:

$(function () {
    $("#autocomplete").autocomplete({
        source: "/pathtohandler/handler.ashx",
        minLength: 1,
        select: function (event, ui) {
            $(this).val(ui.item.value);
        }
    });
});

Gestionnaire ASHX:

public class SearchHandler : IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        var term = context.Request.QueryString["term"].ToString();

        context.Response.Clear();
        context.Response.ContentType = "application/json";

        var search = //TODO implement select logic based on the term above

        JavaScriptSerializer jsSerializer = new JavaScriptSerializer();
        string json = jsSerializer.Serialize(search);
        context.Response.Write(json);
        context.Response.End();
    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
}
4
anthonyvscode