SmartPart Teil1: Datenquellen abrufen

Dies ist ein „No-Code“-Beispiel. Das heißt nicht, dass ich keinen Code posten werde sondern, dass man für die realisierung eigentlich keine Zeile Code tippen muss, weil man alles mit den grafischen Editoren im Visual Studio erledigen kann.

Ziel ist es ein UserControl zu erzeugen, mir dem man Daten aus einer SQL Datenbank abrufen und anzeigen kann.

In Visual Studio erzeugt man zunächt ein neues Web User Control. Ein Projekt ist an dieser Stelle nicht nötig, es reicht der Weg über „Datei>Neu>Datei“.

Unterhalb der Control-Direktive in der ersten Zeile erzeugt man zunächst ein <div>-Tag. Das kann man auch ganz komfortabel aus der Toolbox (Strg+Alt+X, Abschnitt „HTML“) erledigen. Um dem Ganzen etwas mehr Glanz zu verleihen kann man danach das „style“-Attribut des <div>-Tags mithilfe des Visual Studio Designers editieren. Einfach den Cursor im <div> platzieren und auf F4 drücken um das „Eigenschaften“-Fenster aufzurufen. Dort bei dem Schlüßelwort „style“ auf den „…“-Button klicken.

Visual Studio Style Designer

Visual Studio Style Designer

Danach werden noch ein paar ASP.NET-Steuerelemente benötigt:

  • <asp:TextBox … /> –  Zur Eingabe eines Suchbegriffs
  • <asp:Button … /> – Zum Auslösen des PostBacks und damit zur Verarbeitung der Anfrage
  • <asp:GridView … /> – Zur Anzeige des Ergebnisses. Das GridView ist ein äußerst mächtiges Steuerelement. Es kann Daten aus verschiedensten Quellen anzeigen. Zudem beherrscht es Paging und Sortierung. Es muss an eine Datenquelle gebunden werden.
  • <asp:SqlDataSource> – Stellt die Verbindung zur SQl Datenbank her und speichert Abfragen.

Die TextBox und den Button findet man in der Tollbox unter „Standard“, das GridView und die SqlDataSource im Bereich „Data“.

Zunächst muss die Datenquelle konfiguriert werden. Dazu klickt man auf das „SmartTag“ (der kleine Pfeil an dem Steuerelement oben rechts).

datafetcher-datasource-cfg4

Konfiguration der Datenquelle (1)

Die folgenden Schritte sind Dialoggestützt, daher werde ich hier nur die wichtigsten Einstellungen ansprechen und für den Rest die Bilder sprechen lassen.

datafetcher-datasource-cfg0

Konfiguration der Datenquelle (2)

Hier gleich der erste Hinweis: Das UserControl wird später im Verzeichnis der Webanwendung abgelegt. Dieses Verzeichnis genießt von Seiten der Code Access Secutriy nicht so viel Vertrauen wie andere speicherorte. Daher ist im ConnectionString der Datenquelle keine „Integrated Security“ (also Windows-Authentifizierung) erlaubt. Aus diesem Grund verwende ich hier die „SQL Server Authentication“. Der generierte ConnectionString soll nicht abgespeichert werden. Das würde dafür sorgen, dass der ConnectionString in der Web.Config bereitgestellt werden muss. Wenn man ihn nicht speichert wird er in das XML des Steuerelements im UserControl eingebettet.

Konfiguration der Datenquelle (3)

Konfiguration der Datenquelle (3)

Im folgenden Dialog kann man sich die Abfrage zusammenklicken.

Konfiguration der Datenquelle (4)

Konfiguration der Datenquelle (4)

Ohne eine Zeile Code zu schreiben kann man nun auf Benutzereingaben zugreifen und diese zu einem Sql-Statement zusammenbauen lassen.

Konfiguration der Datenquelle (5)

Konfiguration der Datenquelle (5)

Zu guter letzt kann man das Statement und noch gestestet werden. Danach verbindet man die konfigurierte Datenquelle mit des GridView und ist eigentlich schon fertig.

GridView mit SqlDataSource verbinden

GridView mit SqlDataSource verbinden

Am Ende des Tages sollte der Code etwa so aussehen:

<%@ Control Language="C#" ClassName="DataFetcher" %>

<div style="background-color: #FFFF99; border: 3px solid #FFCC00; padding: 10px; width: 300px">
<h3>Northwind Database</h3>
<table style="width:100%;">
 <tr>
  <td><asp:TextBox ID="tbEingabe" runat="server"></asp:TextBox></td>
  <td><asp:Button ID="btnSenden" runat="server" Text="Suchen" /></td>
 </tr>
</table>
<hr />
<asp:GridView ID="gvAusgabe" runat="server"
              AllowPaging="True"
              AllowSorting="True"
              AutoGenerateColumns="False"
              CellPadding="4"
              DataSourceID="NorthwindDataSource"
              ForeColor="#333333" GridLines="None">
  <FooterStyle BackColor="#5D7B9D"
               Font-Bold="True" ForeColor="White" />
  <RowStyle BackColor="#F7F6F3" ForeColor="#333333" />
  <Columns>
     <asp:BoundField DataField="ProductName"
                     HeaderText="ProductName"
                     SortExpression="ProductName" />
     <asp:BoundField DataField="UnitPrice"
                     HeaderText="UnitPrice"
                     SortExpression="UnitPrice" />
     <asp:BoundField DataField="UnitsInStock"
                     HeaderText="UnitsInStock"
                     SortExpression="UnitsInStock" />
  </Columns>
  <PagerStyle BackColor="#284775"
              ForeColor="White" HorizontalAlign="Center" />
  <SelectedRowStyle BackColor="#E2DED6"
                    Font-Bold="True" ForeColor="#333333" />
  <HeaderStyle BackColor="#5D7B9D"
               Font-Bold="True" ForeColor="White" />
  <EditRowStyle BackColor="#999999" />
  <AlternatingRowStyle BackColor="White"
                       ForeColor="#284775" />
</asp:GridView>
</div>

<asp:SqlDataSource ID="NorthwindDataSource" runat="server"
                   ConnectionString="Data Source=ppedv-moss;Initial Catalog=Northwind;User ID=sa;Password=geheim"
                   ProviderName="System.Data.SqlClient"
                   SelectCommand="SELECT [ProductName], [UnitPrice], [UnitsInStock] FROM [Alphabetical list of products] WHERE ([CategoryName] LIKE '%' + @CategoryName + '%')">
   <SelectParameters>
     <asp:ControlParameter ControlID="tbEingabe"
                           Name="CategoryName"
                           PropertyName="Text" Type="String" />
   </SelectParameters>
</asp:SqlDataSource>

Nun muss die Datei nur noch deployed werden. Im wahren Leben würde sich das am besten mit einer SharePoint-Solution machen lassen, für jetzt reicht es aber wenn man im Verzeichnis der Webanwendung (z.B. C:InetPubwwwrootwssVirtualDirectories80) einen neuen Ordner anlegt mit dem Namen „UserControls“ und die Datei dort hineinkopiert.

Platzieren des UserControls

Platzieren des UserControls

Um das UserControl nun wie ein WebPart im SharePoint einbinden zu können muss man natürlich das SmartPart installiert haben. Dieses platziert man dann auf einer beliebigen WebPart-Seite und wechselt über „Bearbeiten>Freigegebenes WebPart bearbeiten“ in die Editor Zone.

SmartPart aus der Catalog Zone auswählen

SmartPart aus der Catalog Zone auswählen

SmartPart konfigurieren

SmartPart konfigurieren

Aus der DropDown-Liste wählt man das UserControl aus und: Tada! Fertig.

Nach dem Bestätigen der Einstellung ist das UserControl einsatzbreit und die SharePoint-Benutzer können die Datenquelle anzapfen und durchsuchen.

datafetcher-deploy3

Das Ergebnis

SmartPart Anleitungen

Das das SmartPart das Entwickeln von WebParts für SharePoint erheblich erleichtern kann ist kein Geheimnis. Die Idee ein Web User Control in einem WebPart zu hosten ist offenbar gut genug, als dass Microsoft diesen Ansatz zu einem Bestandteil der SharePoint Tools in Visual Studio 2010 machen will. Wer nicht solange warten will findet hier ein paar Anleitungen zur Arbeit mit dem SmartPart. Sie entstanden während der Vorbereitung auf die Sessions, welche ich auf der diesjähige ASP konferenz in Burghausen gehalten habe.

SmartParts

SmartParts

In den folgenden Tagen werde ich Anleitungen und Codebeispiele zu folgenden SmartPart-Themen veröffentlichen

  • Datenquellen abrufen
  • Datenquellen abrufen mit AJAX
  • Konfiguration von UserControls mit Attributierung von Eigenschaften
  • Konfiguration von UserCotrols mit einem ToolPart
  • Verbinden von UserControls
  • Verbinden von UserControls mit AJAX

Also, dran bleiben.

SmartPart (v1.3) für SharePoint: CallBack-Problem mit AJAX

Als ich mich kürzlich vorbereitend für die diesjährige ASP konferenz in Burghausen mit dem hervorragenden SmartPart für SharePoint (1.3) beschäftigt habe bin ich auf einige kleine Hindernisse mit der Verwendung von AJAX gestoßen. Nachdem ich dafür nun praktikable Lösungen gefunden habe möchte ich sie euch natürlich nicht vorenthalten.

SharePoint für den Einsatz mit AJAX vorbereiten

Dazu gibt es im Netz hunderte Anleitungen. Die meiner Ansicht nach sinnvollsten sind:

  • Enabling .NET 3.5 in SharePoint 2007 Sites, the Lazy Way von Jan Tielen
    Jan Tielen beschreibt eine schnelle Methode um die benötigten Einträge in die Web.Config einer SharePoint Website zu bekommen. Ein Eintrag wird allerdings nicht automatisch erledigt. Da dies in seinem Posting leider nur in den Kommentaren erwähnt wird hier nochmal von mir: Folgender Eintrag muss zusätzlich noch im SafeControls-Abschnitt in die Web.Config eingetragen werden.
<SafeControl Assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" 
                     Namespace="System.Web.UI" 
                     TypeName="*" 
                     Safe="True" />

Achja, selbstverständlich muss auf dem Server das aktuelle .Net Framework 3.5 installiert sein.

UserControl mit AJAX erzeugen

Mit Hilfe der SmartTemplates lässt sich dann ohne großen Aufwand ein UserControl erzeugen, mit AJAX Steuerelementen, wie zum Beispiel dem UpdatePanel ausstatten und deployen. Soweit so gut.

Problem

Beim ersten Testen kam es zu einem sehr seltsamen Fehler: Das erste Absenden eines CallBacks funktionierte einwandfrei. Folgende dann nicht mehr. Nach einigem Untersuchen mit dem JavaScript-Debugger und Fiddler fand ich zumindest heraus, dass tatsächlich kein CallBack abgesendet wurde. Das hieß, der Fehler lag beim Client, nicht beim Server. Aber Die Client-Skripte funktionierten fehlerfrei.

Was war also des Rätsels Lösung? Nuja, hätte ich Mike Ammerlaans Blog-Post genauer gelesen wäre es mir sofort aufgefallen.

“Windows SharePoint Services JavaScript has a “form onSubmit wrapper” which is used to override the default form action.  This work is put in place to ensure that certain types of URLs, which may contain double byte characters, will fully work across most postback and asynchronous callback scenarios.  However, if your scenarios do not involve double byte character URLs, you may successful disable this workaround and gain the ability to use ASP.NET AJAX UpdatePanels.”

Es gibt also einen Workaround in WSS der URLs beim Post- beziehungsweise CallBack parst und eventuell umformt. Das führt zu Problemen mit dem UpdatePanel.

Die Lösung

Einfach innerhalb des UserControls einen kleinen JavaScript-Block einfügen der dieses Workaround deaktiviert.

    <script type='text/javascript'>
        _spOriginalFormAction = document.forms[0].action;
        _spSuppressFormOnSubmitWrapper = true;
    </script>

Das ist alles. Und schon funktioniert’s.