Web Service 基础

 一 在Web Service中运用Session

在web service中如下定义

 [WebMethod(EnableSession = true )]
public  String UpdateSessionHitCount()
{
        count
++;
        
if (Session["HitCount"== null)
    
{
            Session[
"HitCount"= 1;
        }

        
else
   
{
            Session[
"HitCount"= ((int)(Session["HitCount"])) + 1;
        }

        
return "You have accessed this service " + Session["HitCount"].ToString() + " times.Count="+count.ToString();
}

在客户端如下调用


        SessionService sessionService 
=   new  SessionService();
        sessionService.CookieContainer 
=   new  System.Net.CookieContainer();
        sessionService1.UpdateSessionHitCount()

发现如下现象:

在同一执行过程中UpdateSessionHitCount调用多少次,HitCount的值就增加多少次,而页面刷新或者重新执行则HitCount又从1开始。所以推断:只有同一SessionService的调用才是同一个Session。

但是又有不好理解的地方:

如果同一对象的调用是一个Session,那跟调用本地对象时的计数不是一样吗?那还要Session干什么?

于是又有以下实验:

     private   int  count  =   0 ;
    
public  SessionService ()  {

        
//Uncomment the following line if using designed components 
        
//InitializeComponent(); 
    }

在web service中定义一个全局变量,然后在UpdateSessionHitCount的方法中将Count++

  [WebMethod(EnableSession = true )]
    
public  String UpdateSessionHitCount()
    
{
        count
++;
        ......
      
//return count
   }

发现每次调用Count的值都是1。

结论:

客户端new 一个SessionService对象,然后调用其方法,似乎只new 了一次,其实每次调用都是一个新的对象(对象产生的过程还在学习中)。但是客户端同一个SessionService的多次调用是一个Session。所以这个Session的用法和平时所常见的Session用法还不是完全相同。

 二 在Web Service中运用Application变量

[WebMethod(EnableSession  =   false )]
    
public  String UpdateApplicationHitCounter()
    
{
        
if (Application["HitCounter"== null)
        
{
            Application[
"HitCounter"= 1;
        }

        
else
        
{
            Application[
"HitCounter"= ((int)Application["HitCounter"]) + 1;
        }

        
return "You have accessed this service " + Application["HitCounter"].ToString() + " times.";
    }
 

这和运用Session的区别是EnableSession不用设置为True,而且不用设置CookieContainer为System.Net.CookieContainer的新实例。而这在运用Session时是必须设置的。

三 用于异步 WebMethod 调用的基于事件的新模型

在web服务中HelloWorld方法如下:

    [WebMethod]
    
public   string  HelloWorld()  {
        Thread.Sleep(
5000);
        
return "Hello World";
    }

同步调用

        HelloWorldWaitService service  =   new  HelloWorldWaitService();
        DateTime startTime 
=  DateTime.Now;
        service.HelloWorld();
        DateTime endTime 
=  DateTime.Now;
        TimeSpan timeFromStartToEnd 
=  endTime  -  startTime;
        output.Text 
=   " Total Time (in seconds):  "   +  timeFromStartToEnd.TotalSeconds.ToString();
   

异步调用

   protected   void  ParallelButton_Click( object  sender, EventArgs e)
    
{
        HelloWorldWaitService service 
= new HelloWorldWaitService();
        service.HelloWorldCompleted 
+= this.HelloWorldCompleted;
        Session[
"StartTime"= DateTime.Now;
        service.HelloWorldAsync(
"first call");
        service.HelloWorldAsync(
"second call");
    }

    
public   void  HelloWorldCompleted(Object sender, HelloWorldCompletedEventArgs args)
    
{
        String whichCall 
= (string)args.UserState;
        
if (whichCall.Equals("second call"))
        
{
            
//we can now compute total time for two asynchronous calls
            DateTime endTime = DateTime.Now;
            DateTime startTime 
= (DateTime)Session["StartTime"];
            TimeSpan timeFromStartToEnd 
= endTime - startTime;
            output.Text 
= "Total Time (in seconds): " + timeFromStartToEnd.TotalSeconds;
        }

    }

其中异步调用的结果在args.result中。从调用HelloWorld方法所需的时间来看,同步调用大致是5.0311534妙, 异步调用两次是5.2655239,同步调用一次是5.0624028。

 四 允许运行时选择 Web 服务的 ASP.NET Web 服务客户端

可以将值存储在配置文件中,而不是对 Web 服务的位置进行硬编码或在客户端代理中使用默认位置。这样,您或管理员可以在不更改代码的情况下更改配置文件中的位置。

      HelloWorldService service  =   new  HelloWorldService();
      
// Change the location of the Web service in machine.config if desired
      service.Url  =  System.Configuration.ConfigurationSettings.AppSettings[ " WSUrl " ];
      output.Text 
=  service.HelloWorld();

 

 五 根据架构对传入消息进行验证的 Web 服务

若要在服务上验证消息,请使用 XmlValidatingReader。验证消息的最佳位置是在 SOAP 扩展中。这使您可以完全控制 SOAP 消息的内容,并可以在执行相对来说代价较高的反序列化步骤之前拒绝不符合架构的消息。

请注意,本示例在 WebMethod 体中验证消息。这样做是为了简单。无论在什么位置,验证消息的步骤都是相同的。有关 SOAP 扩展中的验证的更多信息,请参考以下 MSDN article(MSDN 文章)

[WebService(Namespace  =   " http://tempuri.org/ " )]
[WebServiceBinding(ConformsTo 
=  WsiProfiles.BasicProfile1_1)]
public   class  MessageValidationService : System.Web.Services.WebService  {

    
private string returnMessage = "Success! Validation was successful.";

    
public MessageValidationService () 
    
{
        
//Uncomment the following line if using designed components 
        
//InitializeComponent(); 
    }


    [WebMethod]
    
public string SendToValidator(string input)
    
{
        XmlTextReader tr 
= new XmlTextReader(input,XmlNodeType.Document,null);
        XmlValidatingReader vr 
= new XmlValidatingReader(tr);

        XmlSchemaCollection schemas 
= new XmlSchemaCollection();
        schemas.Add(
"Microsoft.Samples.Web.Services""http://localhost/quickstartv20/webservices/samples/MessageValidation/Book.xsd");
        vr.Schemas.Add(schemas);
        vr.ValidationType 
= ValidationType.Schema;
        vr.ValidationEventHandler 
+= new ValidationEventHandler(ValidationHandler);
        
try
        
{
            
while (vr.Read())
            
{
                
//do nothing
            }

        }

        
catch (Exception ex)
        
{
            returnMessage 
= "Failure. An Exception was received, most likely indicating malformed XML. Message: " + ex.Message;     
        }

        
return returnMessage;
    }

    
public void ValidationHandler(object sender, ValidationEventArgs args)
    
{
        returnMessage 
= "Failure. Validation was not successful. Message: " + args.Message;
    }
   
    
}

 六 引发带有自定义信息的 Soap 异常的 ASP.NET Web 服务

服务器可以使用 SoapException 将自定义错误信息发送到客户端。引发(但未捕获)SoapException 以后,服务器以 SOAP 错误的形式在网络上发送错误信息。该 SOAP 错误在客户端上被反序列化回 SoapException。在 SOAP 错误的 Detail 元素中发送自定义(计算机可读的)错误信息。一个 SOAP 错误还包括一条可以人读的错误信息、一个错误代码和一个可选的 SOAP actor。

示例代码:

服务端:

[WebMethod]
    
public   string  ThrowSoapException()  {
        
string myNS = "Microsoft.Samples.XmlMessaging.WebServices.SoapExceptionSample";
        
if (true)
        
{
            XmlDocument doc 
= new XmlDocument();
            XmlNode detail 
= doc.CreateNode(XmlNodeType.Element, SoapException.DetailElementName.Name, SoapException.DetailElementName.Namespace);

            XmlNode errorType 
= doc.CreateNode(XmlNodeType.Element, "ErrorType", myNS);
            errorType.InnerText 
= "Validation";

            XmlNode linePos 
= doc.CreateNode(XmlNodeType.Element, "Position", myNS);
            linePos.InnerText 
= "11";

            XmlNode lineNum 
= doc.CreateNode(XmlNodeType.Element, "Line", myNS);
            lineNum.InnerText 
= "24";

            detail.AppendChild(errorType);
            detail.AppendChild(linePos);
            detail.AppendChild(lineNum);

            
string errorMsg = "处理消息时遇到错误(see Detail element for more information)";
            SoapException exc 
= new SoapException(errorMsg,SoapException.ClientFaultCode,"",detail);
            
throw exc;        
        }

        
return "Hello World";    
    }

客户端:

 SoapExceptionService service  =   new  SoapExceptionService();
        
try
        
{
            
string returnValue = service.ThrowSoapException();
        }

        
catch  (SoapException exception)
        
{
            output.Text 
= "遇到Soap异常";
            message.Text 
= "  " + exception.Message;
            
if (exception.Actor == "")
            
{
                actor.Text 
= " (empty)";
            }

            
else
            
{
                actor.Text 
= "" + exception.Actor;
            }

            StringBuilder builder 
= new StringBuilder();
            StringWriter writer 
= new StringWriter(builder);
            XmlTextWriter xtw 
= new XmlTextWriter(writer);
            xtw.WriteString(exception.Detail.OuterXml);
            xtw.Flush();
            detail.Text 
= builder.ToString();
            xtw.Close();
        }

 七 SOAP Header

本示例演示如何使用 ASP.NET Web 服务对 SOAP 标头的支持。该示例使用一个授权标头,该标头与含有用户名/密码信息的请求一起发送。第一次调用 WebMethod 时未包括 SOAP 标头,因此失败。第二次调用 WebMethod 时包括 SOAP 标头,因此成功返回。

Sample Code:

服务端

/// <summary>
/// AuthHeader class extends from SoapHeader
/// </summary>

public   class  AuthHeader : SoapHeader
{
    
public string Username;
    
public string Password;
}

/// <summary>
/// Summary description for SoapHeaders
/// </summary>

[WebService(Namespace  =   " http://tempuri.org/ " )]
[WebServiceBinding(ConformsTo 
=  WsiProfiles.BasicProfile1_1)]
public   class  SoapHeaders : System.Web.Services.WebService 
{

    
public AuthHeader sHeader;

    [WebMethod]
    [SoapHeader(
"sHeader")]
    
public string SecureMethod() {
        
if (sHeader == null)
            
return "错误: 请提供身份凭据";
        
string usr = sHeader.Username;
        
string pwd = sHeader.Password;

        
if(AuthenticateUser(usr,pwd))
        
{
            
return "成功";
        }

        
else
        
{
            
return "失败";
        }

    }

    
private bool AuthenticateUser(string usr, string pwd)//用于验证身份
    {
        
if ((usr != null&& (pwd != null))//可能是查询数据库
        {
            
return true;
        }

        
return false;
    }
    
}

客户端:

Response.Write( " <font face='verdana'><h4>Using Soap Headers for Custom Authentication</h4> " );
        
//  Create a new instance of the UsingSoapHeaders
        
//  proxy class used to call the remote .asmx file
        SoapHeaders h  =   new  SoapHeaders();
        h.Credentials 
=  System.Net.CredentialCache.DefaultCredentials;

        
//  Call the secure method without credentials
        Response.Write( " <h5>First call result without SOAP Header: </h5> " );
        
try
        
{
            Response.Write(
"<p>");
            Response.Write(h.SecureMethod());
            Response.Write(
"</p>");
        }

        
catch  (Exception ex)
        
{
            Response.Write(
"<pre>");
            Response.Write(ex.StackTrace);
            Response.Write(
"</pre>");
        }


        
//  Create a new instance of the AuthHeader class
        AuthHeader myHeader  =   new  AuthHeader();
        
// WARNING: This sample is for demonstration purposes only.  Username/password information is sent in plain text,
        
// which should never be done in a real application. It is not secure without modification.  
        myHeader.Username  =   " JaneDoe " ;
        myHeader.Password 
=   " password " ;
        
//  Set the AuthHeader public member of the
        
//  UsingSoapHeaders class to myHeader
        h.AuthHeaderValue  =  myHeader;
        
//  Call the secure method with credentials
        Response.Write( " <h5>Second call result with SOAP Header: </h5><p> "   +  h.SecureMethod()  +   " </p></font> " );

客户端执行结果如下:

Using Soap Headers for Custom Authentication
First call result without SOAP Header:

错误: 请提供身份凭据

Second call result with SOAP Header:

成功

 八 UseDefaultCredentials 功能的简单 Web 服务

对于客户端代理类的实例来说,如果将 UseDefaultCredentials 属性设置为 true,则客户端将使用默认凭据对 Web 服务进行身份验证。例如:

UseDefaultCredentialsService service  =   new  UseDefaultCredentialsService();
service.UseDefaultCredentials 
=   true ;

 将 UseDefaultCredentials 属性设置为 true 等效于下列代码行

service.Credentials  =  System.Net.CredentialCache.DefaultCredentials;

同时,还需要在站点部署后在IIS中去掉服务端匿名访问,允许Windows集成身份验证。

总结:

本次练习主要参考ASPNET2.0的QuickStart示例,学习了Web 服务调用,会话状态的使用,同步、异步调用,验证,授权,异常。以及WSDL.exe的常见用法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值