asp.net Js调用 WebService



ASP.Net AJAX(Atlas)终于集成到.Net Framework v3.5中了。使用方式和以往的很相识,只是名字空间稍微发生了改变。
本文将主要讲解最基本最常见的用法。附件中有Sample代码。

Sample 1: 调用WebService


建立一个WebService在站点目录下,添加属性ScriptService
using System.Web.Script.Services; // <-- 添加名字空间


namespace AjaxSample
{
   
/// <summary>
   
/// Summary description for Proxy
   
/// </summary>
    [WebService(Namespace = " http://www.ajaxsample.org/ " )]
    [WebServiceBinding(ConformsTo
= WsiProfiles.BasicProfile1_1)]
    [ToolboxItem(
false )]
    [ScriptService]
// <-- 添加此属性
    public class Proxy : System.Web.Services.WebService
    {

        [WebMethod]
       
public int Add( int a, int b)
        {
           
return a + b;
        }
    }
}


在需要调用的页面中添加ScriptManager,并添加对这个WebService的引用,使用相对路径.
< asp:ScriptManager ID ="ctlScriptManager" runat ="server" >
   
< services >
       
< asp:servicereference Path ="/Proxy.asmx" InlineScript ="false" />
   
</ services >
</ asp:ScriptManager >


调用方式非常简单,和以往一样,名字空间.类名称.方法名称( 参数n, 回调函数)
< input type ="button" value ="异步调用 Add" onclick ="OnBtnAddClicked()" />
< script language ="javascript" type ="text/javascript" >
function OnBtnAddClicked()
{
    AjaxSample.Proxy.Add( 1, 2, OnAddCallback);
}

function OnAddCallback(result)
{
    alert(result);
}
</ script >


注意:正式编码的时候,请将JS放到页面对应JS文件中,并注意方法命名。

最后得到的页面就是:
    < form id ="form1" runat ="server" >
   
< div >
       
< asp:ScriptManager ID ="ctlScriptManager" runat ="server" >
           
< services >
               
< asp:servicereference Path ="/Proxy.asmx" InlineScript ="true" />
           
</ services >
       
</ asp:ScriptManager >
       
       
< input type ="button" value ="异步调用 Add" onclick ="OnBtnAddClicked()" />
       
< script language ="javascript" type ="text/javascript" >
        function OnBtnAddClicked()
        {
            AjaxSample.Proxy.Add( 1, 2, OnAddCallback);
        }

        function OnAddCallback(result)
        {
            alert(result);
        }
       
</ script >
   
       
< hr />
   
</ div >
   
</ form >





Sample 2: WebService返回XML类型的数据


在实际应用中,经常需要从WebService返回复合型数据,在客户端通过XPath进行处理。下面讲解如何做到处理XML类型的返回。

首先添加一个WebService方法返回XmlDocument类型,注意属性的写法,其中ResponseFormat= ResponseFormat.Xml指明了返回的数据类型,这个是必须的。
        [WebMethod]
        [ScriptMethod(ResponseFormat
= ResponseFormat.Xml, UseHttpGet = false )]
       
public XmlDocument GetXmlDoc()
        {
            XmlDocument doc
= new XmlDocument();
            doc.LoadXml(
@" <?xml version=""1.0""?>
<xmlRoot>
  <genericInfo>
    <content>1</content>
    <senderEmail>2</senderEmail>
  </genericInfo>
</xmlRoot>
" );
           
return doc;
        }


在需要的页面中同样添加ScriptManager.,并添加对这个WebService的引用,使用相对路径.
< asp:ScriptManager ID ="ctlScriptManager" runat ="server" >
   
< services >
       
< asp:servicereference Path ="/Proxy.asmx" InlineScript ="false" />
   
</ services >
</ asp:ScriptManager >


使用一个按钮来触发
< input type ="button" value ="Sampe 2:获取XML类型的返回" onclick ="OnBtnGetXmlClicked()" />
< script language ="javascript" type ="text/javascript" >
function OnBtnGetXmlClicked()
{
    AjaxSample.Proxy.GetXmlDoc(OnGetXmlCallback);
}

function OnGetXmlCallback(result)
{
    alert(result.selectSingleNode("//xmlRoot/genericInfo/content/text()").nodeValue);
}
</ script >


注意:正式的开发中,JS应该写到页面对应的JS文件中,且注意命名。
到这里就结束了吗?这个时候,用IE测试一切正常,但是使用Firefox,会出现错误。

 附件: 您所在的用户组无法下载或查看附件

在页面的*.cs文件中,加入Firefox的XPath查询补丁,这样就可以了。
using iVAS.Infrastructure;

namespace AjaxSample
{
   
public partial class InvokeWebService : PageBase
    {
       
protected void Page_Load( object sender, EventArgs e)
        {
            Javascript.IncludeJS(JavascriptFile.FirefoxXPath);
        }
    }
}



Sample 3: 调用页面上的静态方法

调用页面上的静态方法和调用WebService有很多相似之处。首先在页面上放入ScriptManager控件,并指定EnablePageMethods属性为true

< asp:ScriptManager ID ="ctlScriptManager" runat ="server" EnablePageMethods ="True" />


然后在*.cs文件中加入方法:
[WebMethod( EnableSession = true )]
public static int Add( int a, int b)
{
   
return a + b;
}


最后就可以在页面中直接调用了,下面是全部页面代码:
< form id ="form1" runat ="server" >
< div >
   
< asp:ScriptManager ID ="ctlScriptManager" runat ="server" EnablePageMethods ="True" />
       
     
     
</ div >
< input type ="button" runat ="server" id ="btnInvoke" onclick ="OnBtnInvokeClicked()" value ="调用" />
< script language ="javascript" type ="text/javascript" >
function OnBtnInvokeClicked()
{
    PageMethods.Add( 4, 3, OnAddCallback);
}

function OnAddCallback(result)
{
    alert(result);
}
</ script >
</ form >



Sample 4: 不刷新更新页面内容
在很多情况下,需要不刷新页面更新页面的部分内容,那么这就需要用到UpdatePanel了。有如下页面代码
< form id ="form1" runat ="server" >
< div >
   
< asp:ScriptManager ID ="ctlScriptManager" runat ="server" />
   
< asp:UpdatePanel ID ="ctlPanel" runat ="server" RenderMode ="Inline" UpdateMode ="Conditional" >
       
< ContentTemplate >
           
< asp:Label runat ="server" ID ="lblInfo" ></ asp:Label >
       
</ ContentTemplate >
       
< Triggers >
           
< asp:AsyncPostBackTrigger ControlID ="btnInvoke" />
       
</ Triggers >
   
</ asp:UpdatePanel >
   
< hr />
   
< asp:Button runat ="server" ID ="btnInvoke" Text ="Get Time"
        onclick
="btnInvoke_Click" />
</ div >
</ form >


其中的按钮btnInvoke触发服务器事件btnInvoke_Click。服务器事件为
protected void btnInvoke_Click( object sender, EventArgs e)
{
    lblInfo.Text
= DateTime.Now.ToLongTimeString();
}


运行Sample可以看到,点击按钮后,页面在不刷新的情况下就能够显示当前时间。而服务端的写法于平时无异,主要是ASP.Net标签的写法。




首先是ScriptManager,这在AJAX页面中是必须的。然后是UpdatePanel标签,这个标签表示包括了刷新的部分。
RenderMode 表示UpdatePanel最终呈现的HTML元素。Block(默认)表示<div>,Inline表示<span>UpdateMode 更新模式,Always表示不管有没有Trigger,其他控件都将更新该UpdatePanel, Conditional表示只有当前UpdatePanel的Trigger
ChildrenAsTriggers 当UpdateMode属性为Conditional时,UpdatePanel中的子控件的异步回送是否会引发UpdatePanle的更新。

            < Triggers >
               
< asp:AsyncPostBackTrigger ControlID ="btnInvoke" />
           
</ Triggers >


这个标签表示触发异步挥发的条件,具体请看MSDN.可以设置ControlID为服务器控件ID.或者设置EventName为服务器事件名称。


Sample 5: 在UpdatePanel更新前后加入JS代码

经常地,需要在发送一个AJAX请求的时候,需要显示一个进度动画或者Loading...之类的文字,而在得到服务器返回后则做其它一些操作。那么这就需要在客户端中添加JS执行这些操作。

接着上一个例子的代码来,在*.aspx文件中添加了如下代码:
Sys.WebForms.PageRequestManager.getInstance().add_initializeRequest(InitializeRequestHandler);
Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(BeginRequestHandler);
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler);
Sys.WebForms.PageRequestManager.getInstance().add_pageLoading(PageLodingHandler);
Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(PageLoadedHandler);

// 初始化请求时调用,可以在此时取消请求或者检测是否同时有其它请求
function InitializeRequestHandler(sender, args)
{
   
var prm = Sys.WebForms.PageRequestManager.getInstance();
   
   
var strMsg = " 当前是否有未完成的请求 = " + prm.get_isInAsyncPostBack()
             
+ " /n当前请求的触发控件ID = " + args.get_postBackElement().id
             
+ " /n/n是否继续?点击Cancel取消发送 " ;
   
   
if ( ! window.confirm(strMsg) )
    {
       
// 取消当前请求
        args.set_cancel( true );
       
return ;
    }
   
   
// 取消未完成的请求
    if ( prm.get_isInAsyncPostBack() )
        prm.abortPostBack();
       
    document.getElementById(
" txtLog " ).innerText = " InitializeRequestHandler " ;
}

// 开始发送请求
function BeginRequestHandler(sender, args)
{
   
// var elem = args.get_postBackElement();
    document.getElementById( " txtLog " ).innerText += " /r/nBeginRequestHandler " ;
}

// 得到请求响应并已经更新了页面
function EndRequestHandler(sender, args)
{
    document.getElementById(
" txtLog " ).innerText += " /r/nEndRequestHandler " ;
}

// 得到响应并且更新了页面,(注意,不管同步还是异步都会触发这个)
function PageLodingHandler(sender, args)
{
    document.getElementById(
" txtLog " ).innerText += " /r/PageLodingHandler " ;
}

// 得到响应还没有更新页面
function PageLoadedHandler(sender, args)
{
    document.getElementById(
" txtLog " ).innerText += " /r/PageLoadedHandler " ;
}


这5个挂钩分别是可选了,也就是说你只需要挂接自己需要的。这里只是做为范例所以全部例举出来了

initializeRequest:
在该事件的处理函数中,我们可以进行一些额外的、在将请求发送回服务器端之前的附加任务,例如取消即将发出的异步请求、修改某个将要发送回服务器的参数信息、检测当前是否有重复的请求等

beginRequest:异步请求即将发送时触发的事件,在该事件的处理函数中,我们可以显示出某段提示更新的信息(UpdateProgress控件)。

pageLoding:异步请求正在进行时触发的事件,在该事件的处理函数中,我们可以为UpdatePanel即将到来的更新进行一些准备,例如释放使用过的资源等。同样在该事件的处理函数中我们还可以及检查服务器端发送过来的状态信息,并根据不同的状态完成相应的操作控制。

pageLoaded:异步请求返回时触发的事件,在该事件的处理函数中,我们可以访问到更新完成后UpdatePanel中新的内容。

endRequest:异步请求完成时触发的事件,在该事件的处理函数中,我们可以显示更新中可能遇到的异常信息、隐藏UpdateProgress控件、或是其他一些什么别的附加操作等。



Sampe 6: 在母版页及内容页中使用AJAX

在母版页和内容页中使用AJAX唯一的不同是ScriptManager。在母版页中放入ScriptManager,而内容页放入ScriptManagerProxy就可以了。下面是母版页代码:
< html xmlns ="http://www.w3.org/1999/xhtml"; >
< head runat ="server" >
   
< title > 在母版页中使用AJAX </ title >
   
< asp:ContentPlaceHolder ID ="cpHead" runat ="server" >
   
</ asp:ContentPlaceHolder >
</ head >
< body >
   
< form id ="form1" runat ="server" >
   
< div >
       
< asp:ScriptManager ID ="ctlScriptManager" runat ="server"
            EnablePageMethods
="True" />
       
< asp:ContentPlaceHolder ID ="cpMain" runat ="server" >
       
</ asp:ContentPlaceHolder >
   
</ div >
   
</ form >
</ body >
</ html >


以下是内容页的代码
< asp:Content ID ="Content1" ContentPlaceHolderID ="cpHead" runat ="server" >
</ asp:Content >
< asp:Content ID ="Content2" ContentPlaceHolderID ="cpMain" runat ="server" >
   
< asp:ScriptManagerProxy ID ="ctlScriptManagerProxy" runat ="server" >     
    
   
</ asp:ScriptManagerProxy >
   
< input type ="button" runat ="server" id ="btnInvoke" onclick ="OnBtnInvokeClicked()" value ="调用" />
   
< script language ="javascript" type ="text/javascript" >
    function OnBtnInvokeClicked()
    {
        PageMethods.Add( 4, 3, OnAddCallback);
    }
   
    function OnAddCallback(result)
    {
        alert(result);
    }
   
</ script >
</ asp:Content >


调用方式和其它是一样的




PS:
这些都只是最基本的用法,到这里,基本能够应付大部分的开发了。
Atlas中还有对于ProgressBar、Timer的封装,如果需要,请自行参阅相关文档

需要注意的几个问题:
1.跨域之间的AJAX调用一般很少,如果很比较,可以使用Mash-UP,桥接技术。本质上就是HTTP请求的转发
2.对于Drag & Drop,MS也提供了很多种方便的方法,可以自己google
3.UpdatePanel中间尽量少用第3放控件,因为根据MSDN的说法,放如UpdatePanel中间的控件必须符合很多要求,如Response.Write PreRender之类,所以MS不能保证任何控件都能够做到。
Jerry.Wang 最后编辑于 2008-07-14 11:16:59
 
 
补充:直接使用异步提交,不更新页面

        protected void Page_Load( object sender, EventArgs e)
        {
            ScriptManager.GetCurrent(
this ).RegisterAsyncPostBackControl(btnSubmit);
        }

       
protected void btnSubmit_Click( object sender, EventArgs e)
        {
           
// ............
        }


btnSubmit是按钮
 
 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值