ASP.net Grundlagen (Stand 2006)
Diese Dokumentation soll keine Programmier Kenntnisse vermitteln, sie soll das Grobkonzept von ASP.net veranschaulichen und Hilfestellung geben, wie Fehler gefunden werden und vermieden werden können.
Grundlagen
Was ist eine ASP.net Applikation?
Ein Vergleich dazu gibs in der Unixwelt kaum. Grob beschrieben ist eine ASP.net Applikation eine Ansammlung von Dateien in einem Verzeichnis (Applikationsverzeichnis). Diese Dateien haben alle einen bestimmten Zweck in diesem „Applikationsverzeichnis“. Da wären z.B. das /bin
Verzeichnis, die web.config und global.asax (Der Zweck dieser Elemente in einer Applikation wird auf den nächsten Seiten verdeutlicht).
Dann gibs in dieser Applikation noch die aspx Dateien, diese stellen die „Oberfläche“ der Applikation dar. Sie geben den generierten HTML Code an den User aus und greifen dabei auf Programmcode zu der sich in einer .dll Dateien im Bin Verzeichnis befindet. Im Ganzen ist eine Applikation aber anzusehen wie ein Programm, welches über eigene Applikationsvariablen, Sessionvariablen und Ereignisse verfügt, all dies wird in einer solchen Applikation gekapselt.
Das alles und noch mehr (für uns erstmal nicht relevante Elemente) ergeben zusammen eine ASP.net Applikation. Auf den nächsten Seiten wird die Struktur im Filesystem zum leicherteren Verständnis nochmal aufgeführt.
Wie Funktionierts?
Die Technik oder auch die Programmierung unter ASP.net ist nicht mehr vergleichbar mit den alt bekannten Technologien wie z.B. PHP oder ASP 3.0. Bei beiden wurde der Code nur geparsed und dann seinem Schicksal überlassen, anders bei ASP.net. Um das Prinzip zu verstehen, sollte man die wichtigsten Komponenten kennen. Die wohl wichtigste Komponente ist die Runtime (Common Language Runtime -> CLR) welche den Code der verschiedenen .net Sprachen wie VB.net, C# oder managed C++ in eine Zwischensprache kompiliert, die Rechteanforderungen des Codes überprüft und dann
ähnlich wie Java, in einer eigenen Umgebung (Runtime) ablaufen lässt. Dabei kümmert sich die Runtime auch um das Speichermanagement in Form des GarbageCollectors, der einfach ausgedrückt alles im Speicher killt, was nicht mehr benötigt wird. Bei C++ usw.. wäre das noch Aufgabe des Code Autors gewesen.
Eine weitere, wichtige Komponente ist die Framework Class Library, kurz FCL. Diese stellt tausende von Klassen, Funktionen, Typen, Interfaces usw.… bereit, sozusagen der Werkzeugkasten eines Programmierers. Unterteilt wird die FCL in so genannte Namespaces, in welche sich die einzelnen Klassen organisieren. Jeder Namespace wurde zu einem bestimmten Zweck geschaffen. So ist z.B. der Namespace System.IO für .net sowas wie die FSO Komponente für das klassische ASP, also zuständig für Dateibasierte Operationen wie kopieren, löschen usw. Kenntnisse der anderen .net Komponenten sind für diese Dokumentation nicht erforderlich.
Was bedeutet Managed und Unmanaged?
Managed ist alles, was von der .net Laufzeitumgebung (CLR) ausgeführt und verwaltet wird. Klassischer nativer Code wie z.B. com Komponenten sind unmanaged. Diese läuft nicht innerhalb der .net Runtime und basieren auf nativen Code. Auf unmanged Code kann laus der Runtime heraus zugegriffen werden, was aber in den meisten Sharedhosting Angeboten durch Thrustlevel verhindert wird.
Was ist eine Assembly?
Eine Assembly ist die Grundeinheit einer .net Anwendung und liegt im Falle von ASP.net in einer .dll im bin Verzeichnis der Applikation vor. Diese enthält den größten Teil des Applikationsprogrammcodes im MSIL (Microsoft Intermediate Language). Außerdem enthält eine Assembly selbst beschreibende Metadaten über Name, Version und Rechte Anforderungen und ist somit im Deployment besser zu handhaben als com. Leider tritt hier auch eines der größten Irrtümer auf. Eine com .dll Datei ist nicht gleichzusetzen mit einer .net dll. Eine .net Assembly .dll Datei kann ohne weiteres zutun unserseits verwendet werden. Com, also auch unmanaged .dlls wiederum erfordern händisches Sysadmin eingreifen und haben mit einer managed .net Assembly nichts zu tun, trotz der gleichen Dateiendung.
Filestruktur / Komponenten einer ASP.net Applikation
Diese Struktur stellt ein Beispiel Webspace da. Sie enthält 2 Applikationen, die Hauptapplikation und eine SubApplikation. Bilder und HTML Files wurden hier nicht berücksichtigt, könnten sich aber an jeder Stelle Befinden und hätten kein direkten Einfluss auf die Applikation.
Root
Hauptapplikationsverzeichnis - Beherbergt die Applikationen innerhalb der IIS Site. Eine .net Applikation in einem Applikationsverzeichnis ist ein in sich geschlossener Bereich wobei jede Applikation Ihre eigenen Applikationsereignisse, Variablen usw.… erzeugt und verwaltet, und so von anderen Applikationen kapselt. So könnte in diesem Beispiel die Applikation CorrectSubApplication nicht auf Applikationsereignisse oder Applikationsvariablen der Hauptapplikation zugreifen.
/bin
Assembly Verzeichnis. Ablage der .dll Assemblys Dateien.
InCorrectSubApplication
Ein Beispiel für eine falsch angelegte ASP.net Applikation ohne Applikationsverzeichnis. Wird üblicherweise von anderen Programmen als Visual Studio angelegt d.h. nicht als Applikationsverzeichnis. Da eine Applikation Ihre Komponenten steht's im eigenem Root sucht, würden sich in der InCorrectSubApplication/web.config getroffene Einstellungen nicht z.B. auf die in dem Verzeichnis liegende noCodeBehind.aspx auswirken. Lösung: entweder
alle .net Komponenten in diesem Verzeichnis wie web.config, /bin usw.… ins Root kopieren oder per Eskalation um eine Umwandlung von nCorrectSubApplication in ein Applikationsverzeichnis bitten.
CorrectSubApplication
Ein Beispiel für eine funktionierende Applikation mit Applikationsverzeichnis. Alle Darin enthaltenden .net Komponenten verhalten sich vollkommen autark vom Rest der IIS Site.
Web.config
XML Konfigurationsdatei für die aktuelle ASP.net Applikation. (ähnlich php.ini für PHP). Details auf den folgenden Seiten.
Global.asax
Behandelt Ereignisse, welche im Lebenszyklus der Applikation auftreten. So z.B. kann der Entwickler bestimmte Aktionen ausführen, wenn die Applikation startet d.h. zum Beispiel kurz nach dem Upload oder wenn der AppPool recycled wurde. Ebenso kann das Ende einer Applikation „behandelt“ werden.
.aspx
Standard ASP.net Datei. Dient bei Verwendung von CodeBehind nur als Frontend. Und beherbergt die Oberfläche für eine ASP.net Applikation.
.aspx.cs / .aspx.vb
Diese Datei Extension sollte selten auf einer produktiven IIS Site zu sehen sein aber leider kommt dies hin und wieder vor. Diese Dateien enthalten den Programmcode in seiner ursprünglichen .net Sprache und sind Bestandteil des CodeBehind Prinzip. Also steht .aspx.cs für C# und aspx.vb für Visual Basic .net. Dieser Code befindet sich nach der Übersetzungsprozedur in der Assembly und sollte (richtiges Deployment vorausgesetzt) nicht auf einer produktiv Umgebung veröffentlicht werden, aber der Vollständigkeit halber hier mit aufgeführt.
.ascx
Stellt ein Benutzersteuerelement dar, welche einfach ausgedrückt als eine Art HTML Template mit Programmcode fungieren. Diese Dateien enthalten eine @Control Direktive (meinst in der 1. Zeile), über die individuelle Einstellungen für diese Datei getroffen werden können, ähnlich bzw. teilw. Identisch mit der @Page Direktive.
Deployment oder auch Upload & Einrichtung einer ASP.net Applikation
Eine .net Applikation benötigt im eigenem Root Verzeichnis eine web.config und optional auch eine global.asax. Vererbung aus übergeordneten Verzeichnissen der Applikation ist nicht möglich.
Beispiel: Man lädt seine .net Applikation in Verzeichnis /Shop mit einem FTP Programm von seiner lokalen Platte ohne weitere Hilfsmittel hoch. Beim
Aufruf erscheint ein Applikationsfehler ohne genauere Informationen. Auch das deaktivieren der CustomErrors in der web.config unter /shop zeigt keine
genaueren Fehlerinformationen.
Lösung: Mit VisualStudio/Visual Basic usw... erstellte Applikationen immer über die Funktion „Projekt kopieren“ auf den Webspace hochladen. Bei
diesem Vorgang wird automatisch von VS ein Applikationsverzeichnis angelegt. Anderfalls, z.B. bei Verwendung von Webmatrix muss ein Applikationsverzeichnis im IIS von Hand angelegt werden.
Woran kann ich also erkennen, dass es sich bei einem Verzeichnis um ein Applikationsverzeichnis handelt?
Ein Applikationsverzeichnis wird von Frontpage genau wie ein Frontpageweb angezeigt und behandelt. Dargestellt wird es mit folgendem Symbol:
Sollte das angebliche Applikationsverzeichnis aufsehen, wie jeder andere Ordner so ist mit 100%iger Wahrscheinlichkeit davon auszugehen, das hier kein
Applikationsverzeichnis für die Anwendung vorhanden ist. Allerdings unterscheiden sich Frontpage Webs und Applikationsverzeichnisse aber das kann man
entweder nur über den IIS einsehen oder es mit entsprechendem Programmcode testet. Aber die beschriebenen Syntome sollten ausreichen um zu Beurteilen, um welche Art von Verzeichnis es sich handelt.
ASP.net Konfiguration
Hier werden die wichtigsten Elemente der web.config vorgestellt welche man zur Fehlersuche kennen sollte.
Eine von VisualStudio generierte Beispiel web.config ist zu finden unter: http://microsoft-edition.com/faq/webconfig.htm
Für ASP.net gibt es 2 Konfigurationsdatein, eine globale machine.config und ein Applikationselement mit dem Namen Web.config. Beide sind hierachisch
aufgebaute XML Konfigurationsdateien für ASP.net Anwendungen. Die machine.config ist für uns nicht wirklich relevant da diese die .net Konfiguration
für den ganzen Server enthält und somit für den Benutzer im SharedHosting meist nicht zugänglich ist. Dennoch sei erwähnt das in dieser Datei die später noch genauer angesprochenen Trustlevel konfiguriert sind.
Die Hierachy in einer Web.config hat im ungefähren dieses Schema:
<configuration>
<system.web>
//Konfiguration
<system.web>
</configuration>
Die wichtigsten Elemente:
<compilation>
Hiermit werden die Optionen für den Compiler definiert. Debug z.B. legt fest, das die Assemblys mit extra Debuginfos kompiliert wird. Das ist z.B. notwendig, um in der Fehlerausgabe eine Codeangabe zu erhalten. Hierdurch wird allerdings auch die Ausführung der Applikation langsamer und die Dateigröße der Assembly wird erhöht. Alternativ kann der Debugmode auch über die Pagedirektive in der einzelnen Seite aktiviert werden. Beispiel:
<%@ Page language="c#" Codebehind=“myFile.aspx.cs" AutoEventWireup="false" Inherits=“namespace.klasse“ debug=“true” %>
<trace>
Hiermit kann die Ausgabe und das verhalten des Trace beeinflusst werden.
Beispiel:
<configuration>
<system.web>
<trace enabled="false" pageOutput="true" requestLimit="15"/>
<system.web>
</configuration>
Alternativ kann der trace auch über die Pagedirektive in der einzelnen Seite aktiviert werden. Beispiel:
<%@ Page language="c#" Codebehind=“myFile.aspx.cs" AutoEventWireup="false" Inherits=“namespace.klasse“ trace=“true” %>
<sessionState>
Das SessionState Element definiert den Ort, andem die SessionDaten
gespeichert werden. Der Default Wert, welchen z.B. VisualStudio setzt, ist
„InProc” d.h. die SessionDaten werden im aktuellen Prozesscontext gespeichert.
Diese Option wäre im SharedHosting nicht wirklich optimal da durch einen
AppPool Recycle alle SessionDaten verloren gehen und dieser wird in
regelmäßigen Abständen durchgeführt. Daher wäre das externe speichern der
Daten mehr als sinnvol. Dazu gibs den Wert “StateServer” im “mode” Attribut.
Dieser stellt bei uns eine default Einstellung dar. Also muss der Entwickler lediglich die folgenden Zeilen aus der web.conig entfernen oder auskommentieren:
<sessionState
mode="InProc"
stateConnectionString="tcpip=127.0.0.1:42424"
sqlConnectionString="data source=127.0.0.1;Trusted_Connection=yes"
cookieless="true"
timeout="20"
/>
Solange der Entwickler also das SessionState Element nicht überschreibt, werden seine Daten extern gespeichert und sind von einem Recycle nicht betroffen.
Interne Abläufe
Diese Grafik soll verdeutlichen, was bei einem Aufruf einer ASPX Seite passiert. Der (unmanaged) IIS nimmt den Request des Users an und leitet diesen über einen ISAPI Filter an die ASP.net Engine weiter, wo der Request entsprechende weiterverarbeitet wird. Im managed Teil wird dann die Applikation aufgerufen, dort werden wiederum noch mal verschiedene Ereignisse durchlaufen. Applikationsereignisse in der global.asax und Seitenereignisse in der jeweiligen Seite. Einige, nicht alle dieser Ereignisse sind in der Grafik aufgeführt. Wichtig: Fehler in der Global.asax wirken sich auf alle Seiten aus d.h. ein Laufzeitfehler dort wird beim Aufruf aller Seiten angezeigt.
Übersetzungsvorgang
Die folgende Grafik ist etwas gröber als die vorangegangene, und zeigt den Ablauf auf einer der niedrigsten Ebenen. Sie verdeutlicht allerdings, warum ASP.net Anwendungen beim 1. Start länger benötigen, als beim 2. Die Begründung liegt im Punkt „Assembly wird kompiliert“. Dabei wird diese nicht nur kompiliert, es werden auch verschiedene Prüfungen durchgeführt wie z.B. Rechte Anforderungen usw.… Da dies aber nur beim Übersetzungsvorgang in nativen Code durchgeführt werden muss, ist der 2. Aufruf bedeutend schneller. Unterteil wurde die gezeigten Aktionen in die 3 Akteure IIS, ASP.net und dem User, der in diesem Fall Programmier und Besucher der Seite gleichzeitig ist.
Den 1. Schritt, also die Kompilierung seines Quellcodes in MSIL nimmt der Entwickler für gewöhnlich mit Visual Studio vor. Ein AppPool Recycle wird alle 24 Std. einmal durchgeführt oder wenn eine bestimmte Ressourcengrenze überschritten wurde.
Fehlerursachen (Suche mit Debug/Trace)
Warum? Mit dem folgendem Abschnitt kann ein weniger geübter Entwickler durch einen Administrator selbst zur Ursache geführt werden, ohne das sich der Administrator auch nur ein Stück Code ansehen muss.
Bei den folgendem handelt es sich nicht um das eigentliche Debuggen wo man sich direkt an den Prozess hängen kann, sondern eher um die
Interpretations vom Fehlern der .net Runtime. Zum richtigem Debuggen wären Admin Rechte notwendig oder aber der Kunde müsste mit seinem
Visual Studio unter dem gleichen User Arbeiten, wie der Worker Process. Beides ist nicht möglich. Kundenpräsenzen sind auch keine
Entwicklungsumgebungen, was wohl immer wieder vergessen wird.
Eine kleine Exception Definition:
Das Wort Exception wird im folgendem Abschnitt oft fallen, daher hier kurz erläutert. Eine Exception ist wörtlich übersetzt eine Ausnahme und soll ausdrücken, das ein nicht vorgesehener Zustand vorliegt. Exception werden vom Codeautor „geworfen“ und könnten durch ein entsprechendes ExceptionHandling in Form von try/catch Blöcken um den verdächtigen Code herum „aufgefangen“ werden. Die meisten Exceptions, mit welchen unsere Kunden in Berührung kommen werden, werden von der FCL, dem .net Framework ausgelöst. Zum größten Teil zu finden im Namespace System.Exception. Beispielanwendung: Wenn man den Wert einer Variable in einem bestimmten Integer (zahlen) Bereich von 5 – 10 halten möchte, kann beim übersteigen eines bestimmten Wert der Variable, ob verändert durch eigenen oder fremden Code, z.B. eine solche Ausnahme ausgelöst werden damit der Konsument des Codes den Fehler entsprechend „behandeln“
kann.
ASP.net Fehlerursachen finden mit Bordmitteln:
Der Text auf der rechten Seite ist der Standardmäßig von ASP.net ausgegebene Fehler. Hierbei handelt es sich meist um ein Fehler im
eigenem Code. Dies kann ein einfacher Syntaxfehler im Code des Kunden oder z.B. auch eine Security Exception sein, welche z.B. ausgelöst wird,
wenn der Code des Kunden auf Resourcen zugreifen möchte, die per Thrustlevel verboten sind oder z.B. der ASP.net User für die Aktion im
Filesystem keine Rechte hat. Da gibs unzählige Möglichkeiten. Um eine genauere Fehlerausgabe zu erhalten, muß nur der von der .net
Runtime ausgegebene Hinweiß befolgt werden der besagt, das daß Attribut „mode“ des Elements „customErrors“ auf den Wert „off“ gesetzt werden
muss.
Server Error in '/CorrectSubApplication' Application. Runtime Error Description: An application error occurred on the server. The current custom error settings for this application prevent the details of the application error from being viewed remotely (for security reasons). It could, however, be viewed by browsers running on the local server machine. Details: To enable the details of this specific error message to be viewable on remote machines, please create a tag within a "web.config" configuration file located in the root directory of the current web application. This tag should then have its "mode" attribute set to "Off". Notes: The current error page you are seeing can be replaced by a custom error page by modifying the "defaultRedirect" attribute of the application's configuration tag to point to a custom error page URL.
Debug Beispiel Security
Server Error in '/aspnetTraining ' Application. Security Exception Description: The application attempted to perform an operation not allowed by the security policy. To grant this application the required permission please contact your system administrator or change the application's trust level in the configuration file. Exception Details: System.Security.SecurityException: Request for the permission of type System.Security.Permissions.EnvironmentPermission, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 failed. Source Error: An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below. Stack Trace: [SecurityException: Request for the permission of type System.Security.Permissions.EnvironmentPermission, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 failed.] System.Security.CodeAccessSecurityEngine.CheckHelper(PermissionSet grantedSet, PermissionSet deniedSet, CodeAccessPermission demand, PermissionToken permToken) +666 System.Security.CodeAccessSecurityEngine.Check(PermissionToken permToken, CodeAccessPermission demand, StackCrawlMark& stackMark, Int32 checkFrames, Int32 unrestrictedOverride) +0 System.Security.CodeAccessSecurityEngine.Check(CodeAccessPermission cap, StackCrawlMark& stackMark) +88 System.Security.CodeAccessPermission.Demand() +62 System.Environment.get_WorkingSet() +45 MiscTools.ASPNETBenchmark.getInfos() in default.aspx.cs:100 MiscTools.ASPNETBenchmark.Button_SysInfos_Click(Object sender, EventArgs e) in default.aspx.cs:105 System.Web.UI.WebControls.Button.OnClick(EventArgs e) +108 System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +57 System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +18 System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +33 System.Web.UI.Page.ProcessRequestMain() +2106 System.Web.UI.Page.ProcessRequest() +218 System.Web.UI.Page.ProcessRequest(HttpContext context) +18 System.Web.CallHandlerExecutionStep.System.Web.HttpApplication+IExecutionStep.Execute() +179 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +87 Version Information: Microsoft .NET Framework Version:1.1.4322.916; ASP.NET Version:1.1.4322.573
Nach Umstellung der customErrors in der web.config der Beispiel Applikation asnetbench werden nun ausführliche Fehler angezeigt. Eine der wichtigesten Information ist die Art der Exception. Hier sieht man z.B., das eine Security Exception ausgelöst wurde, weil die Applikation versucht hat, Umgebungsvariablen auszulesen, was aufgrund unserer Thrustlevel Einstellung verweigert wurde. Wenn der Autor nun genau wissen möchte, wo der Fehler auftrat, kann er auf den StackTrace verwiesen werden. Dieser zeigt die letzten Funktionaufrufe an und somit kann genau rekonstruiert werden, in welcher Funktion/Methode der Fehler auftrat. Als Richtlinie kann man sagen, das die erste Zeile des Trace, welche nicht mit „System.*“ anfängt, für die Exception verantwortlich ist da es sich dabei um Kundencode handelt. In unserem Beispiel wäre es also die Funktion getInfos() der Klasse ASPNETBenchmark des Namespaces MiscTools oder komplett: MiscTools.ASPNETBenchmark.getInfos() in default.aspx.cs:100 Mit diesen Informationen müsste jeder Programmierer den Fehler selbstständig beheben können.
Debug Beispiel Dateioperationen
Ein weiterer, oft gemachte Fehler ist diemangelnde Rechtevergabe für Dateioperationen.Die auch unter UNIX braucht der aktuelle HostRechte zum ändern im Dateisystem.Als Beispiel nehmen wir ein kleines Skript,welches einen einfachen Besucherzählerdarstellt. Die Besucheranzahl wird in einemTextfile gespeichert. Wenn nun jemand die Seitecounter.aspx aufruft, wird zuerst der letzteZählerstand aus der counter.txt gelesen und mit 1addiert. Anschließend wird der neue Wert zurückin die cs_counter.txt geschrieben und der Wertwird dem Besucher ausgegeben.Ohne Änderungen würde beim Aufruf dercounter.aspx eine UnauthorizedAccessExceptionausgelöst werden. Auch hier hilft die von ASP.netausgegebene Fehlermeldung weiter.Im SharedHosting kann der Kunde natürlich nichtper Explorer auf dem Server, um die Rechte zuändern. Hierfür müsste er über Webfiles demNetwork User die Schreib Rechte für dieentsprechende Datei gewähren, auf die mitASP.net schreibend zugegriffen werden soll. Inunserem Fall cs_counter.txt.Ausnahme wäre hier z.B. die Verwendung derImpersonifizierung (siehe auch Fehlermeldung).Dabei haben die aufgerufenen Skripte diegleichen Rechte, wie der aktuell autentifizierteUser. Das funktioniert im Sharedhosting aber nurmit dem u User, welcher dann statt des NetworkUsers über webfiles entsprechende Rechtezugewiesen bekommen muss.Bei Serverkunden ist dies etwas anders. Um dortherauszufinden, welchem User nun die Rechtezugestanden werden müssen, muss zuerst derzugewiesene AppPool lokalisiert werden. Dieserläuft unter einer bestimmten Identität. ImNormalfall ist dies der Network Service oder aufauf deutsch: Netzwerkdienst. Wenn dort einanderer User aufgeführt ist, muss diesem danndas entsprechende Rechte im Filessystemgegeben werden.
Serverfehler in der Anwendung '/schulungen/aspnet'.
Der Zugriff auf den Pfad E:\websites\LocalUser\god\htdocs\schulungen\aspnet\cs_counter.txt wurde verweigert.
Beschreibung: Beim Ausführen der aktuellen Webanforderung ist ein unverarbeiteter Fehler aufgetreten. Überprüfen Sie die
Stapelüberwachung, um weitere Informationen über diesen Fehler anzuzeigen und festzustellen, wo der Fehler im Code verursacht wurde.
Ausnahmedetails: System.UnauthorizedAccessException: Der Zugriff auf den Pfad
E:\websites\LocalUser\god\htdocs\schulungen\aspnet\cs_counter.txt wurde verweigert.
ASP.NET darf auf die angeforderte Ressource nicht zugreifen. Gewähren Sie der ASP.NET-Prozessidentität Zugriffsrechte für die
Ressource. ASP.NET hat eine Standardprozessidentität (gewöhnlich '{MACHINE}\ASPNET' unter IIS 5 bzw. Network Service unter IIS 6),
die verwendet wird, wenn die Anwendung keinen Identitätswechsel ausführen kann. Wenn die Anwendung über <identity
impersonate="true"/> einen Identitätswechsel ausführen kann, wird als Identität gewöhnlich der anonyme Benutzer (normalerweise
IUSR_MACHINENAME) bzw. der authentifizierte Anfragebenutzer verwendet.
Um ASP.NET Schreibrechte für eine Datei zu gewähren, klicken Sie im Explorer mit der rechten Maustaste auf die Datei, wählen
"Eigenschaften" und anschließend die Registerkarte "Sicherheit". Klicken Sie auf "Hinzufügen", um den entsprechenden Benutzer bzw.
eine Gruppe hinzuzufügen. Markieren Sie das ASP.NET-Konto und aktivieren Sie jeweils das Kontrollkästchen für den gewünschten
Zugriff.
Quellfehler:
Beim Ausführen der aktuellen Webanforderung wurde einen unbehandelte Ausnahme generiert. Informationen über den Ursprung und die
Position der Ausnahme können mit der Ausnahmestapelüberwachung angezeigt werden.
Stapelüberwachung:
[UnauthorizedAccessException: Der Zugriff auf den Pfad E:\websites\LocalUser\god\htdocs\schulungen\aspnet\cs_counter.txt wurde
verweigert.]
System.IO.__Error.WinIOError(Int32 errorCode, String str) +393
System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, Boolean useAsync, String
msgPath, Boolean bFromProxy) +888
System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize) +44
System.IO.StreamWriter.CreateFile(String path, Boolean append) +55
System.IO.StreamWriter..ctor(String path, Boolean append, Encoding encoding, Int32 bufferSize) +49
System.IO.StreamWriter..ctor(String path, Boolean append) +66
System.IO.File.CreateText(String path) +32
aspnetTraining.counter.Page_Load(Object sender, EventArgs e) in c:\inetpub\wwwroot\hellogod\counter.aspx.cs:31
System.Web.UI.Control.OnLoad(EventArgs e) +67
System.Web.UI.Control.LoadRecursive() +35
System.Web.UI.Page.ProcessRequestMain() +731
Versionsinformationen: Microsoft .NET Framework Version:1.1.4322.573; ASP.NET-Version:1.1.4322.573
Aber auch hier wird der Nutzen vom StackTrace verdeutlicht. Dies besagt, das der Kunde im Seitenereigniss Page_Load den Fehler Verursachenden Code ausgeführt hat. Die letzte Punkt (System.IO.__Error.WinIOError(Int32 errorCode, String str) +393) ist dann schon Selbsterklärend für den Programmierer.
Trace
Die Informationen der Traceausgabe sind sehr umfangreich und stellen den aktuellen Applikations und Sitzungsstatus dar. Das Wissen darüber ist sehr hilfreich, wenn weniger geübte Entwickler sich monieren dass Ihre Applikationen komische Dinge tun ohne eine Exception auszulösen, also
einfache Logikfehler. Dann kann ein Hint auf die Traceausgabe die Lösung bringen. In diesem stehen alle Werte, die von User an den Server und zurück gesendet wurden, die Stati der einzelnen Steuerelemente inkl. Speicherverbrauch usw… Aktiviert wird die Anzeige entweder in der web.config über das <trace> Element oder direkt in der Page Direktive der aktuellen Seite durch einfaches hinzufügen von trace=“true“. Beim nächsten Aufruf wird anschließend unter der aktuellen Seite alle Client/Server Informationen angezeigt die sich in folgende Kategorien aufteilen:
Anforderungsdetails
Enthält die aktuelle SessionID (Für jeden User wird eine solche eindeutige ID angelegt), den Zeitpunkt, Codierung und Typ der Anforderung inkl. Zurückgegebener HTTP Statuscode.
Überwachungsinformationen
Eine Liste mit den durchlaufenden Seitenereignissen und die dazu benötigte Zeit.
Steuerelementstruktur
Zeigt eine Hierachische Liste aller auf der Seite befindlichen ASP.net Steuerelemente wie z.B. eine Textbox, ein Button usw… und gibt deren Typ, Speicherverbrauch und Größe des von diesem Element übergebenen ViewState, also dem vom Browser per Formular HiddenVariable übergebene
Status des Elements. Hier lässt sich z.B. bei Performanceproblemen schnell das Steuerelement herrausfinden, welches den größten Viewstate erzeugt.
Sitzungsstatus
Name, Typ und Wert aller Sessionvariablen.
Anwendungsstatus
Name, Typ und Wert aller Applicationvariablen.
Cookieauflistung
Alle, von der aktuellen Applikation auf dem Client gesetzten Cookies.
Headerauflistung (Server)
Alle vom Server zurückgegebenen Headerinformationen.
Servervariablen
Wie auch ein Apache hat auch der IIS Servervariablen. Diese setzen sich zusammen aus Informationen über den anfragenden Client und Information über die Serverumgebung, sind ebenfalls weitestgehend identisch mit den Apache Servervariablen.
CodeBehind
Das ASP.net Codebehind Prinzip trennt komplett den Code vom HTML, ähnlich einem Template System. Dabei werden alle gestalterischen Elemente, incl.
HTML Controls usw… in der .aspx Seite platziert, welche dann vom .net Code des Codes „hinter“ der .aspx Seite gesteuert und gefüllt werden. Es ist natürlich
auch weiterhin möglich, wie beim klassischen ASP oder PHP Code direkt in die aufzurufende Seite zu stecken und so mit HTML zu vermischen. Das sieht
ungefähr wie folgt aus:
<% @Page Language="C#" %>
<% @Import Namespace="System.IO" %>
<script language="C#" runat="server">
// Hier kommt der Code rein
</script >
Das ist zwar für kleine Skripte vom Vorteil aber bei schon mittelgroßen Anwendungen ist das CodeBehind Prinzip unschlagbar.
.method private hidebysig instance void Button_Transfer_Click(object sender, class [mscorlib]System.EventArgs e) cil managed { // Codegröße 23 (0x17) .maxstack 3 IL_0000: ldarg.0 IL_0001: ldfld class [System.Web]System.Web.UI.WebControls.Label Schulung.Sample::Label_ShowResult IL_0006: ldarg.0 IL_0007: ldfld class [System.Web]System.Web.UI.WebControls.TextBox Schulung.Sample::TextBox_Input IL_000c: callvirt instance string [System.Web]System.Web.UI.WebControls.TextBox::get_Text() IL_0011: callvirt instance void [System.Web]System.Web.UI.WebControls.Label::set_Text(string) IL_0016: ret } // end of method Sample::Button_Transfer_Click
Abbildung 2: IL Code
In der .aspx Seite befindet wird für gewöhnlich in der 1. Zeile die PageDirektive. In dieser wird unter anderem aufgeführt, wo sich der
Codebehind befindet. Ein Beispiel:
<%@ Page language="c#" Codebehind="counter.aspx.cs" AutoEventWireup="false" Inherits="aspnetTraining.counter" %>
Das Attribut CodeBehind gibt den Dateinamen an. Dieser ist relevant vor dem Deployment. Nach dem Deployment ist das Inherits für uns wichtiger. Es gibt an, von welcher Klasse (Angabe erfolgt inkl. Namespace) die aktuelle Seite erbt, also wo sich der Code genau in der Assembly befindet. Das generelle Problem hierbei, die CodeBehind Datei befindet sich in der Assembly (obwohl das Attribute CodeBehind hier etwas anderes vermuten lässt), also in einer der .dll Dateien im /Bin Verzeichnis der Applikation. Daher ist es hier nicht so einfach mal eben den Fremdcode zu überfliegen. Dies wäre zwar möglich aber ist mit großem Aufwand verbunden da 1. die Assembly disasambled werden muss und der daraus gewonnene IL Code ist nicht wirklich leicht zu Supporten ist daher zeigen wir mal eine einzige Methode aus einer einfachen Beispiel Schulungsassembly um das zu verdeutlichen.
Performance
Warum .net Code langsam sein kann
1. Weil es .net ist. Das Prinzip von .net basiert, ähnlich wie Java auf einer Runtime, welche den Code per JIT (Just in Time) Kompiler in Binärcode übersetzt. Dabei wird nicht die verwendete Sprache, wie z.B. C# übersetzt, sondern MSIL (Microsoft Intermediate Language) aus der Assembly (.dll) übersetzt. Dies passiert genau ein mal, beim Start der Applikation. Solang der IIS oder der AppPool nicht resettet wird, oder die Applikation nicht neu in msil übersetzt wird, muß auch die Kompilierung kein weiteres mal erfolgen. Nach der 1. kompilierung läuft .net absolut flüssig. Das ist also normal und nicht änderbar.
2. ASP.net verwendet zum speichern der Zustände von User/WebControls (das kann eine TextBox sein) eine Formular Hiddenvariable, um deren letzten Status zu speichern (Die Abbildung auf der rechten Seite zeigt den Viewstate von nur 2 einfachen Button Controls und 2 Label Elementen). Wenn ein Kunde z.B. tausende von Textfeldern und anderen Formularelementen auf eine Seite packt, bläht sich der so genannte Viewstate mehr und mehr auf und bei langsamen Verbindungen ist dann natürlich bei mehr zu übertragenen Daten, ein Geschwindigkeitsverlust zu spüren. Aber dabei handelt es sich selten um Datenmengen von mehr als 10-20kb was bei einer DSL Verbindung nicht wirklich etwas ausmacht. Aber sollte es bei einem Kunden dennoch zu einem solchen Problem kommen (Besonders bei DataGrid Controls (teilw. große Daten Tabelle)) kann der Viewstate auch deaktiviert werden durch setzen der Property „EnableViewstate“ auf „false“ direkt in der aspx Seite, im Tag des jeweiligen Controls. Wie die Controls dann Ihre alten Daten erhalten, ist Aufgabe des Entwicklers. Session Variablen wären z.B. eine Alternative.
Security
CodeInjection
Das größte Security Problem von ASP.net ist mit Sicherheit Code Injection. Dabei wird über ein Eingabeformular fremder Code zur ausführung gebracht. Ein einfaches Beispiel wäre z.B. ein Suchformular, bei dem der Suchbegriff vom Formular direkt an die Datenbank, ohne Überprüfung weitergeleitet wird. Im Sharedhosting wäre nur mit Datenverlust zu rechnen, aber wenn ein Serverkunde z.B. die AppPool Identität auf ein Administrator Account stellt und auf eine MSSQL mittels Windows Authentication zugreift, so kann ohne Problem jede erdenkliche Aktion durch ein solches Formular ausgeführt werden. Um dagegenzuhalten gibt es so genannte ValidationControls. Mit denen ist es möglich, auf einfachste Weise Formularfelder zu überprüfen.
IUSR
Der IUSR ist für den Anonymen Zugriff zuständig, d.h. wenn ein Besucher eine Seite aufruft, hat er die Identität dieses Users. Wenn dieser User aber für eine Bestimmte Ressource keine
Read Rechte haben, so erscheint eine Passwortabfrage.
Probleme im SharedHosting
Warum funktionieren Applikationen nicht mehr, wenn eine Domain direkt auf das (Sub)Applikationsverzeichnis konnektiert wurde?
Beispiel: Angenommen, es wird eine Applikation hochgeladen in http://www.domainname.tld/myApplication. Dann wird von der Applikation
stehts im Pfad /myApplication nach den Applikations Komponenten wie dem AssemblyOrdner /bin oder der web.config gesucht. Konnektiert
man nun aber die domain domainname.tld direkt auf dem Unterverzeichnis myApplication so würde die Applikation Ihre Komponenten nicht
mehr finden da diese intern weiterhin im Verzeichis .domainname.tld/myApplication ihre Komponenten suchen würde. Durch die direkt
konnektierung ist dieses Verzeichnis aber nicht mehr über die domain erreichbar da Sie selbst per Rewrite auf dieses zeigt. Aus diesem Grund
muss die Domain im Hauptverzeichnis konnektiert bleiben. Von dort kann dann auf das Unterverzeichnis myApplication weitergeleitet werden.
Warum ist kein Zugriff auf Access DBs möglich?
Für Access DBs existiert leider noch kein managed Datenbankprovider und aufgrund unserer Thrustlevel ist kein Zugriff auf unmanaged Code
möglich. Ganz im Gegensatz zum SQL Server. Da es sich bei Access allerdings auch mehr um eine DesktopDatenbank handelt und diese nicht
wirklich für Multiuserzugriffe gemacht wurde, bietet sich hier auf jeden Fall der MSSQL Import an.