微软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,如需转载请自行联系原作者


相关文章
|
4月前
|
人工智能 数据处理 芯片
D1net阅闻 | 英伟达Blackwell芯片机架出现故障 微软等大客户削减部分订单
D1net阅闻 | 英伟达Blackwell芯片机架出现故障 微软等大客户削减部分订单
|
2月前
|
中间件 Go
Golang | Gin:net/http与Gin启动web服务的简单比较
总的来说,`net/http`和 `Gin`都是优秀的库,它们各有优缺点。你应该根据你的需求和经验来选择最适合你的工具。希望这个比较可以帮助你做出决策。
90 35
|
19天前
|
存储 缓存
.NET 6中Startup.cs文件注入本地缓存策略与服务生命周期管理实践:AddTransient, AddScoped, AddSingleton。
记住,选择正确的服务生命周期并妥善管理它们是至关重要的,因为它们直接影响你的应用程序的性能和行为。就像一个成功的建筑工地,工具箱如果整理得当,工具选择和使用得当,工地的整体效率将会大大提高。
48 0
|
4月前
|
人工智能 安全 数据中心
D1net阅闻 | 微软CEO对话特朗普和马斯克:豪掷800亿美元建AI数据中心
D1net阅闻 | 微软CEO对话特朗普和马斯克:豪掷800亿美元建AI数据中心
|
4月前
|
人工智能 搜索推荐 机器人
D1net阅闻|据悉微软致力于在365 Copilot产品中添加非OpenAI模型
D1net阅闻|据悉微软致力于在365 Copilot产品中添加非OpenAI模型
|
4月前
|
人工智能 数据中心 芯片
D1net阅闻 | 400亿美元!OpenAI巨额融资有望落地,软银取代微软成最大投资方
D1net阅闻 | 400亿美元!OpenAI巨额融资有望落地,软银取代微软成最大投资方
|
7月前
|
开发框架 监控 .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
115 5
|
7月前
Visual Studio 快速分析 .NET Dump 文件
【11月更文挑战第10天】.NET Dump 文件是在 .NET 应用程序崩溃或出现问题时生成的,记录了应用程序的状态,包括内存对象、线程栈和模块信息。通过分析这些文件,开发人员可以定位和解决内存泄漏、死锁等问题。在 Visual Studio 中,可以通过调试工具、内存分析工具和符号加载等功能来详细分析 Dump 文件。此外,还可以使用第三方工具如 WinDbg 进行更深入的分析。
355 1
|
8月前
|
安全 Java 网络安全
Android远程连接和登录FTPS服务代码(commons.net库)
Android远程连接和登录FTPS服务代码(commons.net库)
123 1
|
8月前
|
开发框架 .NET API
Windows Forms应用程序中集成一个ASP.NET API服务
Windows Forms应用程序中集成一个ASP.NET API服务
160 9

热门文章

最新文章