none
jQuery ashx und JSON RRS feed

  • Frage

  • Hallo beisammen!

    Ich fummel hier seit geraumer Zeit an der genannten Problemstellung. Ich habe eine ashx-Seite, die mir per LINQ einige Namen holt und diese in den Response-Stream schreibt. Die ID eines Namens wird über eine GUID geliefert.
    Im Frontend nutze ich jQuery (1.4.2) mit zugehöriger Autocomplete Funktion... Und ich habe nicht die geringste Ahnung was zu tun ist, trotz tagelanger Googelei  :-/

    Wie zum Geier bekomme ich jQuery dazu, meine gefilterte Liste anzuzeigen? Ich bekomme immer nur ein trauriges "undefined" in der Liste angezeigt.

    Mal ein wenig Code:

      Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
    
        'Dim ad As Core.Environment.ActiveIdentities = CType(context.Session.Item("identities"), Core.Environment.ActiveIdentities)
        Dim searchFor As String = context.Request.QueryString("term")
        Dim bl As New Core.BusinessLayer.Addresses
        Dim lst As List(Of Core.DataObjects.Addresses) = bl.SearchNames(New Guid("dc8fa31a-e17e-4c8c-b528-f616e30b483d"), searchFor, CInt(My.Resources.SearchRowCount))
    
    
        Dim sb As StringBuilder = New StringBuilder
        Dim items As New System.Collections.Generic.List(Of KeyValuePair(Of Guid, String))
    
        Dim k As KeyValuePair(Of Guid, String)
        Dim name As String
        For Each item In lst
          name = item.LastName & ", " & item.FirstName
          k = New KeyValuePair(Of Guid, String)(item.AdressID, name)
          items.Add(k)
        Next
        'context.Response.Write(sb.ToString)
    
        Dim ser As New JavaScriptSerializer
    
        context.Response.Write(ser.Serialize(items))
    
      End Sub

    Dabei dachte ich mir, dass ich der Einfachheit halber ein KeyValuePair serialisiere.
    Die dazu gehörige Javascript-Funktion sieht folgendermaßen aus:

          $(document).ready(function() {
            $("#<%=txtSearch.ClientID%>").autocomplete
            ({
              source: "../webHandler/SearchAddresses.ashx",
              minLength: 1
            });
          });

    Jetzt muss doch noch irgendwie in die Funktion hinein wie die Daten ankommen.
    Hat mal jemand den entscheidenen Hinweis für mich?

    TIA

    Thomas

    Samstag, 15. Mai 2010 15:57

Antworten

  • Hallo Thomas,

    Ich wollte kein PlugIn nutzen, sodern das eingebaute Autocomplete von jQueryUI nutzen. Dummerweise ist das meine erste Begegnung mit JSON (respektive jQuery) und ich komme mir stellenweise vor wie ein Schwein das ins Uhrwerk schaut.

    Nachstehend ein Beispiel (nicht unbedingt schön, aber funktionierend :)

    Webservice

    Imports System.Web.Services
    Imports System.Web.Services.Protocols
    Imports System.Web.Script.Services
    Imports System.ComponentModel
    
    <WebService(Namespace:="http://tempuri.org/")> _
    <WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
    <ScriptService()> _
    <ToolboxItem(False)> _
    Public Class AutoComplete
      Inherits System.Web.Services.WebService
    
      Protected Persons As List( Of Person )
    
      Public Sub New()
        Persons = New List( Of Person )
        Persons.Add( New Person( 1, "Test Tester" ) )
        Persons.Add( New Person( 2, "Superman" ) )
        Persons.Add( New Person( 3, "Spiderman" ) )
        Persons.Add( New Person( 4, "Suppengrün" ) )
        Persons.Add( New Person( 5, "Thomas Abc" ) )
        Persons.Add( New Person( 6, "Thomas Xyz" ) )
        Persons.Add( New Person( 7, "Thorsten Def" ) )
      End Sub
    
      <WebMethod()> _
      <ScriptMethod( ResponseFormat:=ResponseFormat.Json )> _
      Public Function Search( ByVal Term As String ) As List( Of Person )
        Return Persons.FindAll( Function( Check ) Check.Name.StartsWith( Term, StringComparison.InvariantCultureIgnoreCase ) )
      End Function
    
    End Class
    
    Public Class Person
    
      Private _ID  As Int64
      Private _Name As String
    
      Public Property ID As Int64
        Get
          Return _ID
        End Get
        Set
          _ID = Value
        End Set
      End Property
    
      Public Property Name As String
        Get
          Return _Name
        End Get
        Set
          _Name = Value
        End Set
      End Property
    
      Public Sub New()
        Me.New( -1, String.Empty )
      End Sub
    
      Public Sub New( ByVal ID As Int64, ByVal Name As String )
    
        Me._ID  = ID
        Me._Name = Name
    
      End Sub
    
    End Class


    Webform

    <%@ Page Language="vb" AutoEventWireup="false" CodeBehind="AutoComplete.aspx.vb" Inherits=".AutoComplete1" %>
    
    <!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 runat="server">
      <title></title>
      <link type="text/css" href="/Scripts/jQuery/css/ui-lightness/jquery-ui-1.8.1.custom.css" rel="stylesheet" />	
    	<script type="text/javascript" src="/Scripts/jQuery/js/jquery-1.4.2.min.js"></script>
    	<script type="text/javascript" src="/Scripts/jQuery/js/jquery-ui-1.8.1.custom.min.js"></script>
    
    </head>
    <body>
      <form id="form1" runat="server">
      <div>
    <script type="text/javascript">
      $(function() {
        $("#tags").autocomplete({
          source: function (request, response) {
            $.ajax({
              url: "/WebServices/AutoComplete.asmx/Search",
              data: "{ 'Term': '" + request.term + "' }",
              dataType: "json",
              type: "POST",
              contentType: "application/json; charset=utf-8",
              dataFilter: function (data) { return data; },
              success: function (data) {
                response($.map(data.d, function (item) {
                  return {
                    label: item.Name,
                    value: item.Name
                  }
                }))
              }
            });
          },
          minLength: 1
        });
    
      });
    </script>
    
    <div class="demo">
    
    <div class="ui-widget">
    	<label for="tags">Tags: </label>
    	<input id="tags">
    </div>
    
    </div><!-- End demo -->
    
    
      </div>
      </form>
    </body>
    </html>
    

    Evtl. hilft dir das, da weiter zu kommen.

     


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community
    Sonntag, 16. Mai 2010 14:52
    Moderator

Alle Antworten

  • Hallo Thomas,
    Ich fummel hier seit geraumer Zeit an der genannten Problemstellung. Ich habe eine ashx-Seite, die mir per LINQ einige Namen holt und diese in den Response-Stream schreibt. Die ID eines Namens wird über eine GUID geliefert.
    warum nimmst Du nicht einen Webservice? Da kannst Du dann auch gleich komplexeres als nur ein paar Strings übertragen. Geht zwar auch mit einem Handler, ist aber aufwändiger.

    Wie zum Geier bekomme ich jQuery dazu, meine gefilterte Liste anzuzeigen? Ich bekomme immer nur ein trauriges "undefined" in der Liste angezeigt.

    Zuerst müsste man mal wissen, welches AutoComplete Plugin Du verwendest. Das hier

      http://docs.jquery.com/Plugins/AutoComplete/

    oder doch eher das von jQueryUI?

      http://jqueryui.com/demos/autocomplete/

    Wichtig ist bei beiden, dass die Rückgabe in dem Format ankommt, in dem sie erwartet wird (teils einstellbar über die Optionen bei .autocomplete( ... ), siehe dazu jeweils die Doku der Plugins)

    Bei letzteren sollte die Rückgabe dem JSON Format entsprechen, tut sie bei dir aber nicht.

    Schau Dir ggfs. auch mal das hier und das hier an. Evtl. hilfts dir, das besser zu verstehen.

    Im Webservice würde es bspw. reichen, die Methode mit folgenden Atributen zu versehen:

    <WebMethod( ... )> _
    <ScriptMethod(ResponseFormat = ResponseFormat.Json)> _
    Public Function MachWas( ... ) As ...
      ...
    End Function


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community
    Samstag, 15. Mai 2010 21:02
    Moderator
  • Hallo Stefan,

    erst mal danke für Deine Antwort.
    Ich war so stolz eine funktionierende Handler-Factory aufgesetzt zu haben, dass ich die Webservices dabei völlig aus den Augen verloren habe.
    Jetzt wo Du es sagst...

    Ich wollte kein PlugIn nutzen, sodern das eingebaute Autocomplete von jQueryUI nutzen. Dummerweise ist das meine erste Begegnung mit JSON (respektive jQuery) und ich komme mir stellenweise vor wie ein Schwein das ins Uhrwerk schaut.
    Nichts desto trotz werde ich mich erst mal durch Deine Links arbeiten.

    Noch mal besten Dank

    Thomas

     

    Samstag, 15. Mai 2010 21:44
  • Ich bekomme es immer noch nicht in den Griff.

    Mein Webservice sieht nunmehr folgendermaßen aus:

    Public Class AutoComplete
    Inherits System.Web.Services.WebService
    
    <WebMethod()> _
    <ScriptMethod(ResponseFormat:=ResponseFormat.Json)> _
    Public Function SearchAddresses(ByVal contains As String, ByVal rowCount As Integer) As List(Of KeyValuePair(Of Guid, String))
    
    Dim bl As New Core.BusinessLayer.Addresses
    
    Dim lst As List(Of Core.DataObjects.Addresses) = _
    
    bl.SearchNames(New Guid("dc8fa31a-e17e-4c8c-b528-f616e30b483d"), contains, rowCount)
    
    
    Dim items As New List(Of KeyValuePair(Of Guid, String))
    
    Dim k As KeyValuePair(Of Guid, String)
    
    Dim name As String
    
    For Each item In lst
    
    name = item.LastName & ", " & item.FirstName
    
    k = New KeyValuePair(Of Guid, String)(item.AdressID, name)
    
    items.Add(k)
    
    Next
    
    Return items
    
    End Function
    
    End Class
    

     

    Dazu die Javascriptfunktion:

          $(function() {
            ("#<%=txtSearch.ClientID%>").autocomplete({
              source: function(request, response) {
                $.ajax({
                  url: "webservices/AutoComplete.asmx/SearchAddresses",
                  data: {
                    maxRows: 25,
                    contains: request.term
                  },
    
                  dataType: "json",
                  success: function(data) {

    aber wie gehts da nun weiter?

    TIA Thomas

    Samstag, 15. Mai 2010 23:08
  • Nur so am Rande: MVC bringt ein JsonResult out of the box mit :-)

    http://geekswithblogs.net/michelotti/archive/2008/06/28/mvc-json---jsonresult-and-jquery.aspx

    Sonntag, 16. Mai 2010 11:00
  • Hi Thomas,

    jetzt nicht noch 'ne Baustelle, sonst bekomm ich Stresspusteln ;-)

    Gruß

    Thomas

    Sonntag, 16. Mai 2010 11:55
  • Hallo Thomas,

    Ich wollte kein PlugIn nutzen, sodern das eingebaute Autocomplete von jQueryUI nutzen. Dummerweise ist das meine erste Begegnung mit JSON (respektive jQuery) und ich komme mir stellenweise vor wie ein Schwein das ins Uhrwerk schaut.

    Nachstehend ein Beispiel (nicht unbedingt schön, aber funktionierend :)

    Webservice

    Imports System.Web.Services
    Imports System.Web.Services.Protocols
    Imports System.Web.Script.Services
    Imports System.ComponentModel
    
    <WebService(Namespace:="http://tempuri.org/")> _
    <WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
    <ScriptService()> _
    <ToolboxItem(False)> _
    Public Class AutoComplete
      Inherits System.Web.Services.WebService
    
      Protected Persons As List( Of Person )
    
      Public Sub New()
        Persons = New List( Of Person )
        Persons.Add( New Person( 1, "Test Tester" ) )
        Persons.Add( New Person( 2, "Superman" ) )
        Persons.Add( New Person( 3, "Spiderman" ) )
        Persons.Add( New Person( 4, "Suppengrün" ) )
        Persons.Add( New Person( 5, "Thomas Abc" ) )
        Persons.Add( New Person( 6, "Thomas Xyz" ) )
        Persons.Add( New Person( 7, "Thorsten Def" ) )
      End Sub
    
      <WebMethod()> _
      <ScriptMethod( ResponseFormat:=ResponseFormat.Json )> _
      Public Function Search( ByVal Term As String ) As List( Of Person )
        Return Persons.FindAll( Function( Check ) Check.Name.StartsWith( Term, StringComparison.InvariantCultureIgnoreCase ) )
      End Function
    
    End Class
    
    Public Class Person
    
      Private _ID  As Int64
      Private _Name As String
    
      Public Property ID As Int64
        Get
          Return _ID
        End Get
        Set
          _ID = Value
        End Set
      End Property
    
      Public Property Name As String
        Get
          Return _Name
        End Get
        Set
          _Name = Value
        End Set
      End Property
    
      Public Sub New()
        Me.New( -1, String.Empty )
      End Sub
    
      Public Sub New( ByVal ID As Int64, ByVal Name As String )
    
        Me._ID  = ID
        Me._Name = Name
    
      End Sub
    
    End Class


    Webform

    <%@ Page Language="vb" AutoEventWireup="false" CodeBehind="AutoComplete.aspx.vb" Inherits=".AutoComplete1" %>
    
    <!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 runat="server">
      <title></title>
      <link type="text/css" href="/Scripts/jQuery/css/ui-lightness/jquery-ui-1.8.1.custom.css" rel="stylesheet" />	
    	<script type="text/javascript" src="/Scripts/jQuery/js/jquery-1.4.2.min.js"></script>
    	<script type="text/javascript" src="/Scripts/jQuery/js/jquery-ui-1.8.1.custom.min.js"></script>
    
    </head>
    <body>
      <form id="form1" runat="server">
      <div>
    <script type="text/javascript">
      $(function() {
        $("#tags").autocomplete({
          source: function (request, response) {
            $.ajax({
              url: "/WebServices/AutoComplete.asmx/Search",
              data: "{ 'Term': '" + request.term + "' }",
              dataType: "json",
              type: "POST",
              contentType: "application/json; charset=utf-8",
              dataFilter: function (data) { return data; },
              success: function (data) {
                response($.map(data.d, function (item) {
                  return {
                    label: item.Name,
                    value: item.Name
                  }
                }))
              }
            });
          },
          minLength: 1
        });
    
      });
    </script>
    
    <div class="demo">
    
    <div class="ui-widget">
    	<label for="tags">Tags: </label>
    	<input id="tags">
    </div>
    
    </div><!-- End demo -->
    
    
      </div>
      </form>
    </body>
    </html>
    

    Evtl. hilft dir das, da weiter zu kommen.

     


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community
    Sonntag, 16. Mai 2010 14:52
    Moderator
  • Da die Codeformatierung hier nicht wirklich prickelnd ist und ich nicht weiß, ob da evtl. was weggeschnitten wird, habe ich die beiden Dateien noch als Download bereitgestellt.

    Du kannst die hier herunterladen .

     


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community
    Sonntag, 16. Mai 2010 14:56
    Moderator