ASP.NET Gridview per JQuery befüllen

Folgende Ausführungen sind rein akademischer Natur. Über den Nutzen für die Praxis kann an der ein oder anderen Stelle diskutiert werden. Trotzdem sitze ich mit offenem Mund davor und frage mich noch immer –“das geht ?”

Wenn über moderne Web-Anwendungen gesprochen wird, geht es immer um einen REST-Service, JSON-Daten und einen HTML View der z.B. mit Hilfe von Angular.js befüllt wird. Alles schön getrennt. Ich breche mit allem.

Als Backend kommt eine Webmethod zum Einsatz. Diese wird direkt in die ASPX-Seite eingebaut. Theoretisch auch im ASPX-Teil direkt oder per Codebehind. Die Daten verpacke ich gleich in das Zielformat. Da dies eine HTML Table ist, TR und TD Element. Klassisches XML also. Dank HTTP Compression werden vermutlich auch nicht mehr Daten als im Vergleich zu JSON gesendet.

Die Daten kommen aus der Nordwind-Datenbank und werden ganz klassisch per ADO.NET ausgelesen. Also auch hier kein Entity Model. Wichtig der SQL-Parameter um SQLInjection zu unterbinden.

In meinem Beispiel wird immer nur ein Datensatz gelesen. Die ID wird über den Querystring eingesteuert und mit ein wenig Magie, dank der neuen Funktion ASP.NET FriendlyUrls im Methodenrumpf zugewiesen.

Wer sich bei Zeile 13 ungläubig die Augen reibt: das sind XML Literals, ein VB.NET Sprachfeature.

   1:  Public Class WebForm8
   2:      Inherits System.Web.UI.Page
   3:   
   4:      <WebMethod()>
   5:      <ScriptMethod(UseHttpGet:=True, ResponseFormat:=ResponseFormat.Xml)>
   6:      Public Shared Function loadeins(<QueryString("id")> id As Integer?) As XElement
   7:          Dim con As New SqlConnection(ConfigurationManager.ConnectionStrings
("NorthwindConnectionString").ConnectionString)
   8:          Dim cmd As New SqlCommand("SELECT top 1 [ProductID],[ProductName], 
[CategoryID] FROM [Products] where productid=@id"
, con)
   9:          cmd.Parameters.Add(New SqlParameter("@id", id))
  10:          con.Open()
  11:          Dim dtr As SqlDataReader = cmd.ExecuteReader(CommandBehavior.CloseConnection)
  12:          dtr.Read()
  13:          Dim tablexml = <tr><td><%= dtr(0) %></td>
  14:                             <td><%= dtr(1) %></td>
  15:                             <td><%= dtr(2) %></td>
  16:                         </tr>
  17:   
  18:          Return tablexml
  19:      End Function

 

Die Methode kann per GET aufgerufen werden und liefert XML zurück (Zeile 5).

Als nächstes wird ein GridView in die HTML-Seite deklariert. Da keine Daten direkt gebunden werden, muss das Attribut ShowHeaderWhenEmpty gesetzt werden.

   1:  <button onclick="loadmeins();return false" type="button">lade</button>
   2:  <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
   3:      ShowHeaderWhenEmpty="true">
   4:      <Columns>
   5:         <asp:BoundField DataField="ProductID" HeaderText="ID" />
   6:         <asp:BoundField DataField="ProductName" HeaderText="Name" />
   7:         <asp:BoundField DataField="CategoryID" HeaderText="i" />
   8:      </Columns>
   9:  </asp:GridView>

Jetzt kommt der einzige Teil, bei dem ich mich schmutzig fühle. Code, der einzig dem Zweck dient etwas Fehlendes zu umgehen. Ohne Daten tut das Gridview nämlich nichts. Es ist also völlig sinnfrei im Pageload eine Liste zuzuweisen.

   1:   Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
   2:      GridView1.DataSource = New List(Of String)
   3:      GridView1.DataBind()
   4:   End Sub

Nun fehlt nur noch das JavaScript-Zeugs, glattgebügelt mit JQuery. Der Aufruf der WebMethod erfolgt mit Page und Methodenname. Der Parameter für den gewünschten Datensatz wird im Data Block mitgegeben. Für die Anforderung muss der ContentType noch auf JSON stehen, aber die Rückgabe ist XML. Trotzdem wird hier Text in DataType angegeben, weil dann result in Zeile 10 gleich ein Textstring und kein XMLDocument ist. Spart eine Zeile Code.

Am coolsten ist aber die Methode in Zeile 11. Mit einer einzigen Zeile wird der TR-TD-String an die Tabelle angehängt und zwar an den ersten TR. Also in der Reihenfolge genau anders rum wie gewohnt.

   1:  var id = 0;
   2:  function loadmeins() {
   3:    id++;
   4:    $.ajax({
   5:        type: "GET",
   6:        url: "webform8.aspx/loadeins",
   7:        data: { id: id },
   8:        contentType: 'application/json; charset=utf-8',
   9:        dataType: 'text',
  10:        success: function (result) {
  11:           $('#<%=GridView1.ClientID%> tbody tr:first').after(result);
  12:        },
  13:        error: function(result)
  14:           {
  15:                   alert("Fehler");
  16:                  }
  17:      });
  18:  }

 

Bei jedem Click auf “lade” wird eine neue Zeile eingefügt.

image

So und nun kommt der Teil, wo ich nur staunen kann. Im HTML Source besitzt die Tabelle keinen Tbody. Im DOM allerdings schon (über F12 zu erforschen).

Kommentare sind geschlossen