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 offenen 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. Dieser 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 neuer Funktion ASP.NET FriendlyUrls im Methodenrumpf zugewiesen.
Wer sich bei Zeile 13 die ungläubig die Augen reibt. Das sind XML Literals, ein VB.NET Sprachfeature.
1: PublicClass WebForm8
2: Inherits System.Web.UI.Page
3:
4: <WebMethod()>
5: <ScriptMethod(UseHttpGet:=True, ResponseFormat:=ResponseFormat.Xml)>
6: PublicSharedFunction loadeins(<QueryString("id")> id AsInteger?) As XElement
7: Dim con AsNew SqlConnection(ConfigurationManager.ConnectionStrings
("NorthwindConnectionString").ConnectionString)
8: Dim cmd AsNew 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 (Zeile5).
Als nächstes wird ein GridView in die HTML Seite deklariert. Da keine Daten direkt gebunden werden, muss das Attribut ShowHeaderWhenEmpty gesetzt werden.
1: <buttononclick="loadmeins();return false"type="button">lade</button>
2: <asp:GridViewID="GridView1"runat="server"AutoGenerateColumns="False"
3: ShowHeaderWhenEmpty="true">
4: <Columns>
5: <asp:BoundFieldDataField="ProductID"HeaderText="ID"/>
6: <asp:BoundFieldDataField="ProductName"HeaderText="Name"/>
7: <asp:BoundFieldDataField="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 fehlendes zu umgehen. Ohne Daten tut das Gridview nämlich nichts. Also völlig sinn frei im Pageload eine Liste zuweisen.
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 JavaScripts 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.
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).