Um Seitenelemente per Javascript mit Server-Code zu aktualisieren statt die Seite neu zu laden, bietet ASP.NET seit Langem den ICallbackEventHandler. Mit der Einführung von ASP.NET AJAX haben sich die Möglichkeiten allerdings drastisch vervielfacht und die Implementierung von AJAX-Funktionalität geht mittels WebServices und WebMethods wesentlich einfacher von der Hand.
Vorraussetzung für die Verwendung von ASP.NET AJAX ist zunächst einmal die Installation der ASP.NET Extensions.
Um ein bestehendes ASP.NET-Web mit ASP.NET AJAX zu erweitern, bedarf es einiger Anpassung der web.config:
<configSections>
<!-- ASP.NET AJAX -->
<sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication"/>
<sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="Everywhere" />
<section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication" />
<section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication" />
</sectionGroup>
</sectionGroup>
</sectionGroup>
</configSections>
<pages enableViewState="true">
<controls>
<!-- ASP.NET AJAX -->
<add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</controls>
</pages>
<httpHandlers>
<!-- ASP.NET AJAX -->
<remove verb="*" path="*.asmx"/>
<add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="false"/>
</httpHandlers>
<httpModules>
<!-- ASP.NET AJAX -->
<add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</httpModules>
<compilation debug="true">
<assemblies>
<!-- ASP.NET AJAX -->
<add assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
</assemblies>
</compilation>
Näheres dazu unter Documentation for: ASP.NET Ajax Version 1.0 - Configuring ASP.NET AJAX
Statt der althergebrachten Registrierung von Callback-Referenzen und der Implementierung von RaiseCallbackEvent und GetCallbackResult, kann man nun zum Beispiel in einer beliebigen ASPX-Seite Methoden implementieren und sie über das Attribut WebMethod clientseitig ansprechbar machen:
<System.Web.Services.WebMethod( _
Description:="Ausgabe des Namens des Webservers", _
EnableSession:=True)> _
Public Shared Function GetMachineName() As String
Return HttpContext.Current.Server.MachineName
End Function
-
Wichtig ist die Deklarierung der Methoden als Public Shared, um auf die Methode öffentlich und instanzlos zugreifen zu können.
Zuständig für Vermittlung zwischen Server- und Client-Code ist das neue ScriptManager-Steuerelement, das man in der ASPX-Seite unterbringt:
<asp:ScriptManager ID="ScriptManager1" EnablePageMethods="true" runat="server">
<Scripts>
<asp:ScriptReference Path="MyPage.js"/>
</Scripts>
</asp:ScriptManager>
Die Eigenschaft EnablePageMethods sorgt dafür, dass in die Ausgabe automatisch ein Stück Javascript gerendert wird, dass den Aufruf der in der Seite als WebMethod deklarierten Methoden umsetzt:
<script type="text/javascript">
//<![CDATA[
var PageMethods = function() {
PageMethods.initializeBase(this);
this._timeout = 0;
this._userContext = null;
this._succeeded = null;
this._failed = null;
}
PageMethods.prototype = {
GetMachineName:function(succeededCallback, failedCallback, userContext) {
return this._invoke(PageMethods.get_path(), 'GetMachineName',false,{},succeededCallback,failedCallback,userContext); },
...
(Ausgabe gekürzt)
...
PageMethods.set_path("/MyPage.aspx");
PageMethods.GetMachineName= function(onSuccess,onFailed,userContext) {
PageMethods._staticInstance.GetMachineName(onSuccess,onFailed,userContext); }
//]]>
</script>
Über das Scripts-Unterelement kann man dem ScriptManager das Script mitgeben, in dem man die Client-Funktionalität untergebracht hat. Genausogut kann man dies aber auch über einen Inline-Javascript-Block lösen.
Im Client-Script kann man nun sehr bequem über das Objekt PageMethods auf die Server-Methode zugreifen:
// ---------------------------------------------------------------------------------
function getServerName() {
PageMethods.GetMachineName(onSuccess, onFailure);
}
// ---------------------------------------------------------------------------------
function onSuccess(result, userContext, methodName) {
alert("Name des Web-Servers: " + result);
}
// ---------------------------------------------------------------------------------
function onFailure(error, userContext, methodName) {
if (error !== null) {
alert("Es ist ein Fehler aufgetreten: " + error.get_message());
}
}
-
Sollte trotz korrekter Deklaration des ScriptManager-Steuerelements, im Quelltext der Seite der automatisch generierte
PageMethods-Code fehlen, muss man über das Menü Erstellen die Projektmappe neu erstellen lassen.
