天天看点

基于.NET的WebService的实现

这个专题主要讲述的是webservice,因此这里我们的代码以webservice相关为主,而其他工程,例如:servicegathersite,websitea等,只将简略介绍.

     在vs2003中,开发一个webservice并不是件困难的事,首先,我们新建一个webservice项目(文件->新建->项目->c#->web服务应用程序)

     建完这个工程,我们将看到一个叫service1.asmx的文件,这就是webservice的标准文件,它也有ui的概念,不过我们一般不关注,因此,我们查看其cs代码文件.如果你什么都还没做的话,将看见一个被注释掉的helloworld的webmethod,把注释去掉,在运行,你就可以得到最简单的webservice运行实例了.点击"helloworld"将执行其方法.显然,这个函数对我们的意义只在于宏观的了解了下web服务的写法.

     下面,我们将开始具体介绍webservice的写法.在代码文件里,如果我们写了一个函数后,希望此函数成为外部可调用的接口函数,我们必须在函数上面添上一行代码[webmethod(description="函数的描述信息")],如果你的函数没有这个申明,它将不能被用户引用.如:

[webmethod(description="最简单的方法")]  

  public

string helloworld()  

  {  

   return

"hello world";  

  }   

[webmethod(description="最简单的方法")]

public string helloworld()

{

return "hello world";

}

     这个函数就是外部可调用的接口函数,对用户来说相当于一个api.如果某用户在引用了这个服务后,他调用helloworld()方法,他就将获得"helloworld"这个返回值.

      看到这里,我们是不是发现,其实webservice并不是那么的神秘,它也不过只是个接口,对我们而言,侧重点依然是接口函数的编写.下面,我将给出我们的例子所需要的接口函数.

[webmethod(description="查询以获取需要的课件信息")]  

public xmldatadocument getsiteadata(string assignname)  

{  

  xmldatadocument xd=new xmldatadocument();

//  

  dataset ds=new dataset();  

  cstoreproc cp=new cstoreproc("searchassign");  

  cp.addparin("@keywords",sqldbtype.varchar,30,assignname);  

  cp.addparout("@res",sqldbtype.int);  

  if(cp.selectproc())

//如果执行成功,存储过程  

   cp.mydata.enforceconstraints=false;

//不进行格式严格检查  

   if((int)cp.getreturnvalue("@res")==-1)  

   {  

    string xml="<newdataset></newdataset>";  

    xd.loadxml(xml);  

    return xd;  

   }  

   xd=new xmldatadocument(cp.mydata);  

   xmlnode root1=xd.documentelement;   

   xmlnodelist roots=root1.selectnodes("list");     

   foreach(xmlnode roota

in  roots) 

//为所有元素加上站点名称标记  

    xmlelement link=xd.createelement("sitename");   

    link.innertext=configurationsettings.appsettings["sitename"].tostring();  

    roota.appendchild(link);  

   return xd;  

  }  

  else

return null;  

}   

[webmethod(description="查询以获取需要的课件信息")]

public xmldatadocument getsiteadata(string assignname)

xmldatadocument xd=new xmldatadocument(); //

dataset ds=new dataset();

cstoreproc cp=new cstoreproc("searchassign");

cp.addparin("@keywords",sqldbtype.varchar,30,assignname);

cp.addparout("@res",sqldbtype.int);

if(cp.selectproc()) //如果执行成功,存储过程

cp.mydata.enforceconstraints=false; //不进行格式严格检查

if((int)cp.getreturnvalue("@res")==-1)

string xml="<newdataset></newdataset>";

xd.loadxml(xml);

return xd;

xd=new xmldatadocument(cp.mydata);

xmlnode root1=xd.documentelement;

xmlnodelist roots=root1.selectnodes("list");

foreach(xmlnode roota in roots) //为所有元素加上站点名称标记

xmlelement link=xd.createelement("sitename");

link.innertext=configurationsettings.appsettings["sitename"].tostring();

roota.appendchild(link);

else return null;

这是获取资源站点信息的一个接口函数.里面大部分的代码,我想对于有一定asp.net基础的朋友来说,都应该是一看就明白,这里只说明下cstoreproc,这是我封装的一个存储过程类,主要功能是执行各种类型的存储过程.

        细心的朋友可能会发现这个函数的返回类型似乎比较特殊,是个xml的文档.我们在前面已经说过,webservice只能传输序列化数据,xml显然满足条件,但比如hash表之类的非序列化数据,是不能传输的,xml使用最为广泛,而且考虑到跨平台应用,所以这里我们只以xml数据的传输来示例.

函数功能很简单,只是要返回查询结果,其数据格式是xmldatadocument.当查询失败时(无匹配查询结果),我们构造一个xml,返回一个空记录.否则,我们把查询后的dataset生成一个xmldatadocument,接下来,由于该项目的需要,我加入了一个循环,添加dataset里所没有的节点,站点名称.在这之后,算是完成了一个符合我们期望格式的xml数据文档,我们把它返回.

        好了,webservice的方法函数介绍完了(这里还有个web服务方法,稍后介绍),接下来我们的任务是怎么调用它了.首先把webservice的项目编译完成,假定我们这个服务是针对资源站点a的,我们不妨称其为servicea.先单独运行asmx文件,执行getsiteadata(string assignname)方法,将提示你输入参数,你输入要搜索的内容,点确认,将返回给你一个xml数据,并在ie上显示出来,这就是你搜索到的内容拉.

       这里对servicea的工作再做点介绍,在我们这个项目里,它是资源站点a提供的服务,意思是,它查询的数据将全来源于站点a,而站点a资源添加在本项目也有专门的工程实现.

       好了,回到正题.这里我介绍vs调用webservice的方法,其实其他平台的调用方法也是大同小异.首先我们介绍web引用方式,这种方式我强烈建议调试时使用,非常方便.右击引用,点添加web引用,输入你的webservice地址,如:http://localhost/aspxproject/webservicesolution/sitebservice/service1.asmx,你必须保证你输入的webservice存在.然后引用即可,注意:web引用名将作为你加入的webservice的名字空间.比如你输入了:sitea,那服务的实例化将是这样:sitea.service1

servicea=new sitea.service1();(service1是服务的类名).

       完成了这一步,service的调用似乎变的那么简单,我们已经实现了远程实例化,接下来的远程调用也是一样的容易.下面给出资源采集站servicegathersite的绑定代码(只采集a站点的信息)

//绑定数据  

void binddata()  

   servicea=new sitea.service1();  

   dataset ds=new dataset();  

   xmlnode xmlnode1;  

   xmldatadocument xd=new xmldatadocument();  

   stringbuilder xmlstring1;  

   xmlnode1=servicea.getsiteadata(strsearch);  

   if(xmlnode1==null)

//--存储过程执行失败  

    return;  

   xmlstring1=new stringbuilder(xmlnode1.outerxml);  

   if(xmlstring1.tostring().equals("<newdataset xmlns=\"\"></newdataset>"))  

    return ;  

   xd.loadxml(xmlstring1.tostring());  

   ds.readxml(new xmlnodereader(xd));  

   datagrid1.datasource=ds.tables["list"].defaultview;  

   datagrid1.databind();  

//绑定数据

public void binddata()

servicea=new sitea.service1();

xmlnode xmlnode1;

xmldatadocument xd=new xmldatadocument();

stringbuilder xmlstring1;

xmlnode1=servicea.getsiteadata(strsearch);

if(xmlnode1==null) //--存储过程执行失败

return;

xmlstring1=new stringbuilder(xmlnode1.outerxml);

if(xmlstring1.tostring().equals("<newdataset xmlns=\"\"></newdataset>"))

return ;

xd.loadxml(xmlstring1.tostring());

ds.readxml(new xmlnodereader(xd));

datagrid1.datasource=ds.tables["list"].defaultview;

datagrid1.databind();

       此段代码给出了xml转化成dataset的解决方案,虽然这不是必须的,但毕竟在asp.net里,dataset占的作用之重,谁都知道的.其他的请朋友们先看(呵呵,个中高手就免了)

先简单说明下绑定函数.首先实例化servicea,这个和一般类的实例化并没有不同..接下来用xmlnode1来接受函数的返回值,接下来是构造xml,并将其转化为dataset,这是通用的方法,如果是刚接触不久的朋友,最好能记下这种方法.

<a target="_blank"></a>

     接下来给出异步调用两个服务的代码

   iasyncresult ar1;  

   iasyncresult ar2;  

   serviceb=new siteb.service1();  

   xmlnode xmlnode1,xmlnode2;  

   stringbuilder xmlstring1,xmlstring2;  

   //--简单的异步调用  

   ar1=servicea.begingetsiteadata(strsearch,null,null);  

   ar2=serviceb.begingetsiteadata(strsearch,null,null);  

   xmlnode1=servicea.endgetsiteadata(ar1);  

   xmlnode2=serviceb.endgetsiteadata(ar2);  

   //----------

   if(xmlnode1==null&amp;&amp;xmlnode2==null)

   xmlstring2=new stringbuilder(xmlnode2.outerxml);  

   xmlstring1=makenewxmlstring(xmlstring1,xmlstring2); 

//生成新的xml  

  //生成新xml  

  public stringbuilder makenewxmlstring(stringbuilder str1,stringbuilder str2)  

   str1=str1.replace("&lt;/newdataset&gt;","");  

   str2=str2.replace("&lt;newdataset xmlns=\"\"&gt;","");  

   str1.append(str2.tostring());  

   return str1;  

iasyncresult ar1;

iasyncresult ar2;

serviceb=new siteb.service1();

xmlnode xmlnode1,xmlnode2;

stringbuilder xmlstring1,xmlstring2;

//--简单的异步调用

ar1=servicea.begingetsiteadata(strsearch,null,null);

ar2=serviceb.begingetsiteadata(strsearch,null,null);

xmlnode1=servicea.endgetsiteadata(ar1);

xmlnode2=serviceb.endgetsiteadata(ar2);

//----------

if(xmlnode1==null&amp;&amp;xmlnode2==null) //--存储过程执行失败

xmlstring2=new stringbuilder(xmlnode2.outerxml);

xmlstring1=makenewxmlstring(xmlstring1,xmlstring2); //生成新的xml

//生成新xml

public stringbuilder makenewxmlstring(stringbuilder str1,stringbuilder str2)

str1=str1.replace("&lt;/newdataset&gt;","");

str2=str2.replace("&lt;newdataset xmlns=\"\"&gt;","");

str1.append(str2.tostring());

return str1;

   这有两个需要注意的地方,一个是xml构造,还有就是异步调用的实现,请读者,自己理解

   下面讲下通过dll来引用webservice的方法,我只把流程介绍下.

   首先,在ie输入服务的地址,如:http://www.xxx.com/service.asmx

  然后写输入http://www.xxx.com/service.asmx?wsdl

  打开后,另存为xxx.wsdl

  然后用vs的命令提示符来编译:wsdl /namespace:sitea servicea.wsdl

生成名字空间为sitea的代理类

最后csc /out:servicea.dll /t:library service1.cs ,其中service1.cs为代理类文件

最后引用dll就可以了.

到这里,我们的例子基本也就介绍完了,由于个人的原因,最后一篇可能写的比较仓促,非常惭愧.

不知道写这么多,对学习中的朋友会不会有帮助,里面的东西,很多也算是个人理解,如果出错,还请各位海涵:)