微软AJax.net源码初步分析(2)--服务执行流程

简介:
我以一个最简单的helloworld为例,演示AJax.net源码中调用后台服务的机制,只是列出一些大体的框架,具体细节我还在研究中:)
不当之处,欢迎指正。

我先把例子中的核心代码列出,方便大家阅读。
HelloWorldService服务中:
    [WebMethod(EnableSession  =   true )]
    
public   string  HelloWorld( string  name)
    
{
        String aaa 
= Session["name"].ToString();
        
string hello = String.IsNullOrEmpty(name) ? "无名氏" : name;
        hello 
+= "你好,当前服务器时间是:";
        hello 
+= DateTime.Now.ToUniversalTime() + "   " + aaa;
        
return hello;
    }

HelloWorld.aspx文件:
<% @ Page Language = " C# "  AutoEventWireup = " true "   CodeFile = " HelloWorld.aspx.cs "  Inherits = " _Default "   %>

<% @ Register Assembly = " Microsoft.Web.Extensions "  Namespace = " Microsoft.Web.UI "  TagPrefix = " asp "   %>

<! DOCTYPE html PUBLIC  " -//W3C//DTD XHTML 1.0 Transitional//EN "   " http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd " >

< html >
< head id = " Head1 "  runat = " server " >
    
< title > Hello </ title >

< script type = " text/javascript " >
    function SayHello()
    
{
        var fs 
= HelloWorldService;
        fs.set_defaultSucceededCallback(OnShow);
        fs.HelloWorld(document.getElementById(
"name").value);

    }

    function OnShow(result)
    
{
        var s 
= document.getElementById("result");
        s.innerText 
= result;
    }

</ script >
    
</ head >
< body style = " font-size: 12pt " >
    
< form id = " form1 "  runat = " server " >
    
        
< asp:ScriptManager ID = " ScriptManager1 "  runat = " server " >
            
< Services >
                
< asp:ServiceReference Path = " ~/HelloWorldService.asmx "   />
            
</ Services >
        
</ asp:ScriptManager >
        
< div >
        你的名字:
        
< input type = " text "  maxlength = " 20 "  id = " name "   />
        
< input type = " button "  id = " button1 "  value = " 问候 "  onclick = " SayHello() "   />
        
< div id = " result " ></ div >
        
</ div >
    
</ form >
    
</ body >
</ html >

后台调用机制分析:(都是Microsoft.Web.Extensions.dll反编译后看到的)
1、在AssemblyInfo.cs中声明了如下一些javascript脚本:
 [assembly: System.Web.UI.WebResource("Microsoft.Web.Resources.Timer.bmp", "image/bmp")]
 [assembly: System.Web.UI.WebResource("Microsoft.Web.Resources.Background.gif", "image/gif")]
 [assembly: System.Web.UI.WebResource("Microsoft.Web.Resources.ScriptLibrary.MicrosoftAjaxWebForms.debug.js", "application/x-javascript")]
 [assembly: System.Web.UI.WebResource("Microsoft.Web.Resources.ScriptLibrary.MicrosoftAjaxRuntime.debug.js", "application/x-javascript")]
 [assembly: System.Web.UI.WebResource("Microsoft.Web.Resources.ScriptLibrary.MicrosoftAjax.debug.js", "application/x-javascript")]
 [assembly: System.Web.UI.WebResource("Microsoft.Web.Resources.ScriptLibrary.MicrosoftAjaxWebForms.js", "application/x-javascript")]
 [assembly: System.Web.UI.WebResource("Microsoft.Web.Resources.ScriptLibrary.MicrosoftAjaxRuntime.js", "application/x-javascript")]
 [assembly: System.Web.UI.WebResource("Microsoft.Web.Resources.ScriptLibrary.MicrosoftAjax.js", "application/x-javascript")]

这些javascript脚本也都是作为资源包含在Microsoft.Web.Extensions.dll中的

2、在ScriptManager的OnPreRender中进行如下操作,进行js代码的注册(有的方法是调用其它类里面的):
         // 取得AJax的客户端脚本名称
         private   static   string  GetFullName( string  name, System.Reflection.Assembly assembly)
        
{
            
if (assembly != ScriptReference.AtlasFrameworkAssembly)
            
{
                
return name;
            }

            
return ("Microsoft.Web.Resources.ScriptLibrary." + name);
        }
         // 取得dll中js文件的位置
         string  IClientScriptManager.GetWebResourceUrl(Type type,  string  resourceName)
        
{
            
return this._clientScriptManager.GetWebResourceUrl(type, resourceName);
        }
        

        
// 注册客户段脚本(写入页面的html文件中去)
         void  IClientScriptManager.RegisterClientScriptInclude(Type type,  string  key,  string  url)
        
{
            
this._clientScriptManager.RegisterClientScriptInclude(type, key, url);
        }
         // 注册服务
        
// 取得页面上有哪些服务,如上面的HelloWorldService.asmx服务,然后调用如下语句
         this ._clientScriptManager.RegisterClientScriptInclude(type,  " HelloWorldService.asmx/jsdebug " " HelloWorldService.asmx/jsdebug " );
以上主要是使用.net 2.0新增的 ClientScriptManager类进行客户端脚本的注册,也就是生成我们在页面上看到的如下一段代码:
(通过查看运行时的aspx文件的html代码)
<script src="/Web/WebResource.axd?d=7lZSau3voGpyPgiEEMwJxQ2&amp;t=632965017419375000" type="text/javascript"></script>
......
<script src="/Web/WebResource.axd?d=VbevhO3ptb2WYvwQWrgTHKAWH4jfDIInCsIvYHSSJgRDZKhi9uLV9U_0kyOUMuNB32yLgf_UUzCml8vnGl7OI4r89qpFWhjBi2BmMZGBkApjwmG5MAGWzA_yjFYvRA8w2gdgDWR5RgcQF-F7MVigcyaKFVde2W9oIqW8P4zdL9g1&amp;t=632985966674218750" type="text/javascript"></script>
<script src="HelloWorldService.asmx/jsdebug" type="text/javascript"></script>

3、通过IHttpHandlerFactory接口对服务进行处理:
在web.config中进行注册:
  <httpHandlers>
   <remove verb="*" path="*.asmx"/>
   <add verb="*" path="*.asmx" validate="false" type="Microsoft.Web.Script.Services.ScriptHandlerFactory, Microsoft.Web.Extensions"/>
  </httpHandlers>

  然后在ScriptHandlerFactory中调用如下一段代码:
             public   void  ProcessRequest(HttpContext context)
            
{
                
this._originalHandler.ProcessRequest(context);
            }

        
                
base ._builder.Append(text1).Append( " .set_path = function(value) { \r\n/// <summary>Sets the service url.</summary>\r\n/// <param name=\ " path\ "  type=\ " String\ " >The service url.\r\nvar e = Function._validateParams(arguments, [{name: 'path', type: String}]); if (e) throw e;  " ).Append(text1).Append( " ._staticInstance._path = value; }\r\n " );
                
base ._builder.Append(text1).Append( " .get_path = function() { \r\n/// <summary>Returns the service url.</summary>\r\n/// <returns type=\ " String\ " >The service url.</returns>\r\nreturn  " ).Append(text1).Append( " ._staticInstance._path; }\r\n " );
                
base ._builder.Append(text1).Append( " .set_timeout = function(value) { \r\n/// <summary>Sets the service timeout.</summary>\r\n/// <param name=\ " value\ "  type=\ " Number\ " >The service timeout.\r\nvar e = Function._validateParams(arguments, [{name: 'timeout', type: Number}]); if (e) throw e; if (value < 0) { throw Error.argumentOutOfRange('value', value, Sys.Res.invalidTimeout); }\r\n " ).Append(text1).Append( " ._staticInstance._timeout = value; }\r\n " );
                
base ._builder.Append(text1).Append( " .get_timeout = function() { \r\n/// <summary>Returns the service timeout.</summary>\r\n/// <returns type=\ " Number\ " >The service timeout.</returns>\r\nreturn  " ).Append(text1).Append( " ._staticInstance._timeout; }\r\n " );
                
base ._builder.Append(text1).Append( " .set_defaultUserContext = function(value) { \r\n/// <summary>Sets the service default userContext.</summary>\r\n/// <param name=\ " value\ " >The service default user context.\r\n " ).Append(text1).Append( " ._staticInstance._userContext = value; }\r\n " );
                
base ._builder.Append(text1).Append( " .get_defaultUserContext = function() { \r\n/// <summary>Returns the service default user context.</summary>\r\n/// <returns>The service default user context.</returns>\r\nreturn  " ).Append(text1).Append( " ._staticInstance._userContext; }\r\n " );
                
base ._builder.Append(text1).Append( " .set_defaultSucceededCallback = function(value) { \r\n/// <summary>Sets the service default succeeded callback.</summary>\r\n/// <param name=\ " value\ "  type=\ " Function\ " >The service default succeed callback function.\r\nvar e = Function._validateParams(arguments, [{name: 'defaultSucceededCallback', type: Function}]); if (e) throw e;  " ).Append(text1).Append( " ._staticInstance._succeeded = value; }\r\n " );
                
base ._builder.Append(text1).Append( " .get_defaultSucceededCallback = function() { \r\n/// <summary>Returns the service default succeeded callback.</summary>\r\n/// <returns type=\ " Function\ " >The service default succeeded callback.</returns>\r\nreturn  " ).Append(text1).Append( " ._staticInstance._succeeded; }\r\n " );
                
base ._builder.Append(text1).Append( " .set_defaultFailedCallback = function(value) { \r\n/// <summary>Sets the service default failed callback function.</summary>\r\n/// <param name=\ " value\ "  type=\ " Function\ " >The service default failed callback function.\r\nvar e = Function._validateParams(arguments, [{name: 'defaultFailedCallback', type: Function}]); if (e) throw e;  " ).Append(text1).Append( " ._staticInstance._failed = value; }\r\n " );
                
base ._builder.Append(text1).Append( " .get_defaultFailedCallback = function() { \r\n/// <summary>Returns the service default failed callback function.</summary>\r\n/// <returns type=\ " Function\ " >The service default failed callback function.</returns>\r\nreturn  " ).Append(text1).Append( " ._staticInstance._failed; }\r\n " );
                
                ..
                context.Response.ContentType 
=   " application/x-javascript " ;
                context.Response.Write(text1);

以上代码实际上就是根据页面上有的服务生成对应的javascript代码,比如我们针对上面的HelloWorldService.asmx服务,就会生成如下一段javascript
代码,注册到页面中去:
var HelloWorldService=function() {
this._timeout = 0;
this._userContext = null;
this._succeeded = null;
this._failed = null;
}
HelloWorldService.prototype={
HelloWorld:function(name,succeededCallback, failedCallback, userContext) {
    /// <summary>Invoke the HelloWorld WebMethod</summary>
    /// <param name=\"name\">WebMethod parameter: name(type: String)</param>
    /// <param name=\"succeededCallback\" type=\"function\" optional=\"true\">Callback on successful completion of request</param>
    /// <param name=\"failedCallback\" type=\"function\" optional=\"true\">Callback on failure of request</param>
    /// <param name=\"userContext\" optional=\"true\">User context data (any JavaScript type)</param>
return Sys.Net._WebMethod._invoke.apply(null, [ this, 'HelloWorld','HelloWorldService.HelloWorld',false,{name:name},succeededCallback, failedCallback, userContext]); },_get_path: function() { return HelloWorldService.get_path(); },

set_timeout: function(value) {
    /// <summary>Sets the timeout for this service.</summary>
    /// <param name=\"value\" type=\"Number\">The timeout in milliseconds.</param>
    var e = Function._validateParams(arguments, [{name: 'timeout', type: Number}]);
    if (e) throw e;
    if (value < 0) {
        throw Error.argumentOutOfRange('value', value, Sys.Res.invalidTimeout);
    }
    this._timeout = value;
},
get_timeout: function() {
    /// <summary>Returns the timeout in milliseconds for this service.</summary>
    /// <returns type=\"Number\">The timeout in milliseconds for the service.</returns>
    return this._timeout;
},
set_defaultUserContext: function(value) {
    /// <summary>Sets the default userContext for this service.</summary>
    /// <param name=\"value\">The default userContext for this service.</param>
    this._userContext = value;
},
get_defaultUserContext: function() {
    /// <summary>Returns the default userContext for this service.</summary>
    /// <returns>Returns the default userContext for this service.</returns>
    return this._userContext;
},
set_defaultSucceededCallback: function(value) {
    /// <summary>Sets the default succeededCallback for this service.</summary>
    /// <param name=\"value\" type=\"Function\">The default succeededCallback for this service.</param>
    var e = Function._validateParams(arguments, [{name: 'defaultSucceededCallback', type: Function}]);
    if (e) throw e;
    this._succeeded = value;
},
get_defaultSucceededCallback: function() {
    /// <summary>Returns the default succeededCallback for this service.</summary>
    /// <returns type=\"Function\">Returns the default succeededCallback for this service.</returns>
    return this._succeeded;
},
set_defaultFailedCallback: function(value) {
    /// <summary>Sets the default FailedCallback for this service.</summary>
    /// <param name=\"value\" type=\"Function\">The default FailedCallback for this service.</param>
    var e = Function._validateParams(arguments, [{name: 'set_defaultFailedCallback', type: Function}]);
    if (e) throw e;
    this._failed = value;
},
get_defaultFailedCallback: function() {
    /// <summary>Returns the default failedCallback for this service.</summary>
    /// <returns type=\"Function\">Returns the default failedCallback for this service.</returns>
    return this._failed;
}
}
HelloWorldService._staticInstance = new HelloWorldService();
HelloWorldService.set_path = function(value) { 
/// <summary>Sets the service url.</summary>
/// <param name=\"path\" type=\"String\">The service url.
var e = Function._validateParams(arguments, [{name: 'path', type: String}]); if (e) throw e; HelloWorldService._staticInstance._path = value; }
HelloWorldService.get_path = function() { 
/// <summary>Returns the service url.</summary>
/// <returns type=\"String\">The service url.</returns>
return HelloWorldService._staticInstance._path; }
HelloWorldService.set_timeout = function(value) { 
/// <summary>Sets the service timeout.</summary>
/// <param name=\"value\" type=\"Number\">The service timeout.
var e = Function._validateParams(arguments, [{name: 'timeout', type: Number}]); if (e) throw e; if (value < 0) { throw Error.argumentOutOfRange('value', value, Sys.Res.invalidTimeout); }
HelloWorldService._staticInstance._timeout = value; }
HelloWorldService.get_timeout = function() { 
/// <summary>Returns the service timeout.</summary>
/// <returns type=\"Number\">The service timeout.</returns>
return HelloWorldService._staticInstance._timeout; }
HelloWorldService.set_defaultUserContext = function(value) { 
/// <summary>Sets the service default userContext.</summary>
/// <param name=\"value\">The service default user context.
HelloWorldService._staticInstance._userContext = value; }
HelloWorldService.get_defaultUserContext = function() { 
/// <summary>Returns the service default user context.</summary>
/// <returns>The service default user context.</returns>
return HelloWorldService._staticInstance._userContext; }
HelloWorldService.set_defaultSucceededCallback = function(value) { 
/// <summary>Sets the service default succeeded callback.</summary>
/// <param name=\"value\" type=\"Function\">The service default succeed callback function.
var e = Function._validateParams(arguments, [{name: 'defaultSucceededCallback', type: Function}]); if (e) throw e; HelloWorldService._staticInstance._succeeded = value; }
HelloWorldService.get_defaultSucceededCallback = function() { 
/// <summary>Returns the service default succeeded callback.</summary>
/// <returns type=\"Function\">The service default succeeded callback.</returns>
return HelloWorldService._staticInstance._succeeded; }
HelloWorldService.set_defaultFailedCallback = function(value) { 
/// <summary>Sets the service default failed callback function.</summary>
/// <param name=\"value\" type=\"Function\">The service default failed callback function.
var e = Function._validateParams(arguments, [{name: 'defaultFailedCallback', type: Function}]); if (e) throw e; HelloWorldService._staticInstance._failed = value; }
HelloWorldService.get_defaultFailedCallback = function() { 
/// <summary>Returns the service default failed callback function.</summary>
/// <returns type=\"Function\">The service default failed callback function.</returns>
return HelloWorldService._staticInstance._failed; }
HelloWorldService.set_path(\"/Web/HelloWorldService.asmx\");
HelloWorldService.HelloWorld= function(name,onSuccess,onFailed,userContext) {    /// <summary>Invoke the HelloWorld WebMethod</summary>
    /// <param name=\"name\">WebMethod parameter: name(type: String)</param>
    /// <param name=\"succeededCallback\" type=\"function\" optional=\"true\">Callback on successful completion of request</param>
    /// <param name=\"failedCallback\" type=\"function\" optional=\"true\">Callback on failure of request</param>
    /// <param name=\"userContext\" optional=\"true\">User context data (any JavaScript type)</param>
HelloWorldService._staticInstance.HelloWorld(name,onSuccess,onFailed,userContext); }

4、实际调用
这样服务注册好之后,我们在页面上写的
        var fs = HelloWorldService;
        fs.set_defaultSucceededCallback(OnShow);
        fs.HelloWorld(document.getElementById("name").value);
实际上就是调用注册好的javascript脚本,然后这些脚本再通过通用的AJAX连接XML的异步方式调用后台代码就可以了


    本文转自永春博客园博客,原文链接:http://www.cnblogs.com/firstyi/archive/2006/11/08/554374.html,如需转载请自行联系原作者


相关文章
|
1天前
|
开发框架 监控 .NET
【Azure App Service】部署在App Service上的.NET应用内存消耗不能超过2GB的情况分析
x64 dotnet runtime is not installed on the app service by default. Since we had the app service running in x64, it was proxying the request to a 32 bit dotnet process which was throwing an OutOfMemoryException with requests >100MB. It worked on the IaaS servers because we had the x64 runtime install
|
19天前
|
安全 Java 网络安全
Android远程连接和登录FTPS服务代码(commons.net库)
Android远程连接和登录FTPS服务代码(commons.net库)
17 1
|
1月前
|
开发框架 .NET API
Windows Forms应用程序中集成一个ASP.NET API服务
Windows Forms应用程序中集成一个ASP.NET API服务
85 9
|
4月前
|
存储 运维
使用Visual Studio分析.NET Dump
使用Visual Studio分析.NET Dump
|
2月前
|
存储 运维
.NET开发必备技巧:使用Visual Studio分析.NET Dump,快速查找程序内存泄漏问题!
.NET开发必备技巧:使用Visual Studio分析.NET Dump,快速查找程序内存泄漏问题!
|
3月前
|
存储 NoSQL Redis
【Azure Developer】一个复制Redis Key到另一个Redis服务的工具(redis_copy_net8)
【Azure Developer】一个复制Redis Key到另一个Redis服务的工具(redis_copy_net8)
【Azure Developer】一个复制Redis Key到另一个Redis服务的工具(redis_copy_net8)
|
3月前
|
敏捷开发 设计模式 开发者
【揭秘终极利器】AgileEAS.NET:服务定位器模式的魔法,如何让企业级软件开发瞬间提速?揭秘背后的技术奥秘与实战指南!
【8月更文挑战第16天】AgileEAS.NET是基于DotNet的企业级敏捷开发平台,其服务定位器模式助力构建高度解耦系统。通过全局服务目录动态查找服务,避免硬编码依赖。在AgileEAS.NET中,服务定位器以静态类形式封装服务注册与检索功能。示例展示了如何注册与获取服务实例,如在`UserController`中通过服务定位器使用`IUserService`。此模式整合到框架生命周期管理,便于各处获取服务实例,提升开发效率。然而,应适度使用并考虑依赖注入容器以增强代码可维护性和可测试性。
69 4
|
3月前
|
安全 Java 网络安全
Android远程连接和登录FTPS服务代码(commons.net库)
很多文章都介绍了FTPClient如何连接ftp服务器,但却很少有人说如何连接一台开了SSL认证的ftp服务器,现在代码来了。
99 2
|
3月前
|
开发框架 缓存 .NET
【App Service】在Azure App Service中分析.NET应用程序的性能的好帮手(Review Stack Traces)
【App Service】在Azure App Service中分析.NET应用程序的性能的好帮手(Review Stack Traces)
|
3月前
|
开发框架 .NET 编译器
【Azure Developer】使用Azure PubSub服务示例代码时候遇见了.NET 6.0的代码转换问题
【Azure Developer】使用Azure PubSub服务示例代码时候遇见了.NET 6.0的代码转换问题