Für den ersten Kontakt mit Windows Azure stellt Microsoft mit dem Windows Azure Platform Training Kit eine umfangreiche Sammlung an Beispielen rund um die Azure-Plattform zur Verfügung. Die Freude auf die neue Technologie könnte allerdings sehr schnell getrübt werden, wenn man feststellen muss, dass bereits die simple “Hello-World”-Anwendung aus den Beispielen partout nicht funktionieren will. Viele werden sich hierbei die Frage stellen, was sie falsch gemacht haben oder bzw. was man überhaupt an einem Hello-World Beispiel falsch machen kann. Wenn Sie einer dieser Menschen sind, dann werden Sie den Fehler vermutlich eher im Azure-SDK finden als bei sich selbst.
Mit den Windows Azure Tools für Visual Studio 1.4 hat Microsoft viele Verbesserungen bereitgestellt, die die Entwicklung und das Deployment von Cloud-Anwendungen vereinfachen sollen. Darunter sind auch die neuen ASP .Net Universal Providers, die nun in jedem Web-Role Template enthalten sind und damit die alten Membership-, Role-, Session- und Profile-Provider ersetzen, welche mit der Version 2.0 von ASP.Net eingeführt wurden [1].
Abbildung 1: Eine web.config mit den neuen ASP.Net Universal Providers
Wenn auch die alten Provider immer noch in der web.config vorzufinden sind, werden diese nicht mehr in Azure Deployments verwendet und es werden standardmäßig die neuen Universal Providers aktiviert (siehe Abbildung 1).
Diese Verbesserungen bringen allerdings auch das Problem mit sich, dass der Session State-Provider nun in allen Templates die Default Verbindung verwendet, die wiederum standardmäßig auf eine lokale SQL-Express Datenbank verweist (siehe Abbildung 2).
Abbildung 2: Session Provider mit Verweis auf eine lokale Datenbank
Man kann bereits erahnen, was passieren wird, wenn man versucht dieses Projekt in die Cloud zu deployen. Soweit braucht man aber zunächst nicht zu gehen, es können bei solch einer Konfiguration bereits bei der Verwendung des Local Storage unerwartete Probleme auftreten. So gibt es sicherlich viele Entwickler, die abhängig von ihrer IDE-Konfiguration und installierter Software, mit dem folgendem Berechtigungsproblem konfrontiert werden:
Server Error in ‘/’ Application.
Cannot open database “DATABASE_NAME” requested by the login. The login failed.
Login failed for user ‘NT AUTHORITY\NETWORK SERVICE’.
Dieses Problem ist altbekannt und tritt sehr häufig bei der ASP.Net Entwicklung auf. Hierzu findet man Online sehr viele verschiedene Lösungsansätze, die von dem Deinstallieren bestimmter Software bis hin zu Registry-Hacks reichen. Viele dieser Lösungsansätze bringen letztendlich auch den gewünschten Effekt und beheben in der Regel das Problem. Es gibt jedoch eine Methode die immer funktioniert und zudem sehr einfach und schnell zu realisieren ist.
Hierzu muss man zunächst das SQL Server Management Studio mit Administrator-Rechten öffnen und zu SQL-Server >> Security >> Logins navigieren. Anschließend klickt man auf NT AUTHORITY\NETWORK SERVICE mit der rechten Maustaste und wählt Properties (siehe Abbildung 3).
[Sollte an dieser Stelle der Benutzer NT AUTHORITY\NETWORK SERVICE fehlen, muss man diesen zunächst manuell anlegen und danach wieder mit den o.g. Schritt fortfahren.]
Abbildung 3: Eigenschaften eines Benutzers im Object Browser des SQL Server Management Studios
In dem neu geöffneten Eigenschaftsfenster wählt man links den Tab User Mapping und wählt rechts die Datenbank aus, auf die nicht zugegriffen werden kann. Zuletzt wählt man im unteren Fenster die Rolle db_owner aus und bestätigt das Ganze mit OK (siehe Abbildung 4).
Abbildung 4: Datenbank Rollen eines Benutzers im SQL Server
Dieser Fix beseitigt das Problem in nahezu allen bekannten Fällen, so dass keine Probleme mehr im Zusammenhang mit dem Local Storage auftreten sollten.
Der oben beschriebene Fix behebt allerdings nur Rechteprobleme mit lokalen Datenbanken. Doch was passiert, wenn man ein Windows Azure Projekt, mit der in Abbildung 2 gezeigten web.config in die Cloud deployen will? Das Resultat sieht zunächst wie in Abbildung 5 aus:
Abbildung 5: ASP.Net YSOD (Yellow Screen of Death)
Aus Sicherheitsgründen wird der aufgetretene Fehler verschleiert, so dass er nicht Online von dritten eingesehen werden kann und so wohlmöglich sensitive Daten herausgegeben werden. Will man dennoch den Fehler auf die schnelle einsehen, muss man der web.config den customErrors-Tag hinzufügen. Nach einem erneuten Deployment wird der Fehler offensichtlich:
Server Error in ‘/’ Application.
A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: SQL Network Interfaces, error: 26 – Error Locating Server/Instance Specified)
Wie bereits am Anfang des Artikels darauf hingedeutet wurde, versucht die Anwendung hier innerhalb der Cloud auf eine SQL-Express Datenbank zuzugreifen. Auch für dieses Problem gibt es verschiedene Wege zur Lösung. Man könnte beispielsweise ganz stupide die ASP.Net Universal Providers deinstallieren und hätte somit das Problem in den Griff bekommen. Allerdings ist diese Lösung offensichtlich nicht optimal, da die ASP.Net Universal Providers durchaus ihre Daseinsberechtigung besitzen und es auch Wert sind, verwendet zu werden.
Um das Problem schnell und dennoch elegant zu lösen, sollte man der Anwendung einfach das geben, wonach sie sucht: eine Datenbank.
Zum anlegen einer Datenbank in Windows Azure muss man zunächst das Windows Azure Management Portal aufrufen. Auf der Startseite des Portals wählt man links Database aus und klickt anschließend in der Mitte auf Create a New SQL-Azure Database (siehe Abbildung 6).
Abbildung 6: Windows Azure Management Portal – Bereich Database
In den darauffolgenden Dialogen legt man eine SQL-Azure Datenbank an, die man beispielsweise UniProvider oder UniversalProvider nennt (siehe Abbildung 7).
Abbildung 7: Anlegen einer neuen SQL Azure Datenbank
Nachdem die Datenbank angelegt wurde, muss diese lediglich noch in die web.config der Anwendung eintragen werden. Der einfachste Weg geht hierbei über die Zwischenablage. Dazu lässt man sich zuerst die Connection Strings anzeigen (siehe Abbildung 8), markiert anschließend den Connection String, der unter ADO.Net gelistet wird und kopiert diesen mittels STRG + C in die Zwischenablage.
Abbildung 8: SQL Azure Database – Verbindungsinformationen
Zu allerletzt muss man noch die DefaultConnection in der web.config auf den eben kopierten Connection String aktualisieren
(siehe Abbildung 9).
Abbildung 9: Eintragen einer eigenen Datenbank in der web.config
Hierbei gilt zu beachten, dass das Property MultipleActiveResultSets=True nicht mitkopiert wurde und manuell angelegt werden muss. Nach diesem Schritt und einem erneuten Deployment sollte nun die Anwendung wie gewünscht funktionieren.
“SessionState? Brauch ich nicht!”
Der Lösungsansatz in diesem Beitrag beschreibt sozusagen die optimale Lösung für die eingangs genannten Verbindungsprobleme mit Windows Azure. Wird dagegen der SessionState-Mechanismus nicht benötigt oder ist z.B. für Testzwecke einfach nur eine möglichst schnelle und unkomplizierte Lösung erforderlich, so reicht es aus in der web.config den SessionState-Modus zu deaktivieren (siehe Abbildung 10). Dieser Schritt behebt die beiden Probleme, die in diesem Beitrag beschrieben werden in nur wenigen Sekunden – jedoch mit dem Verzicht auf eine sehr nützliche Funktion.
Abbildung 10: Deaktivierung des Session State Mechanismus in der web.config