| 一 在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(); } 在客戶端如下調(diào)用 SessionService sessionService = new SessionService(); sessionService.CookieContainer = new System.Net.CookieContainer(); sessionService1.UpdateSessionHitCount() 發(fā)現(xiàn)如下現(xiàn)象: 在同一執(zhí)行過程中UpdateSessionHitCount調(diào)用多少次,HitCount的值就增加多少次,而頁面刷新或者重新執(zhí)行則HitCount又從1開始。所以推斷:只有同一SessionService的調(diào)用才是同一個Session。 但是又有不好理解的地方: 如果同一對象的調(diào)用是一個Session,那跟調(diào)用本地對象時的計數(shù)不是一樣嗎?那還要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 } 發(fā)現(xiàn)每次調(diào)用Count的值都是1。 結(jié)論: 客戶端new 一個SessionService對象,然后調(diào)用其方法,似乎只new 了一次,其實每次調(diào)用都是一個新的對象(對象產(chǎn)生的過程還在學(xué)習(xí)中)。但是客戶端同一個SessionService的多次調(diào)用是一個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的區(qū)別是EnableSession不用設(shè)置為True,而且不用設(shè)置CookieContainer為System.Net.CookieContainer的新實例。而這在運用Session時是必須設(shè)置的。 三 用于異步 WebMethod 調(diào)用的基于事件的新模型 在web服務(wù)中HelloWorld方法如下:     [WebMethod] public string HelloWorld() ...{ Thread.Sleep(5000); return "Hello World"; } 同步調(diào)用         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(); 異步調(diào)用   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; } } 其中異步調(diào)用的結(jié)果在args.result中。從調(diào)用HelloWorld方法所需的時間來看,同步調(diào)用大致是5.0311534妙, 異步調(diào)用兩次是5.2655239,同步調(diào)用一次是5.0624028。 四 允許運行時選擇 Web 服務(wù)的 ASP.NET Web 服務(wù)客戶端 可以將值存儲在配置文件中,而不是對 Web 服務(wù)的位置進行硬編碼或在客戶端代理中使用默認位置。這樣,您或管理員可以在不更改代碼的情況下更改配置文件中的位置。        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();  五 根據(jù)架構(gòu)對傳入消息進行驗證的 Web 服務(wù) 若要在服務(wù)上驗證消息,請使用 XmlValidatingReader。驗證消息的最佳位置是在 SOAP 擴展中。這使您可以完全控制 SOAP 消息的內(nèi)容,并可以在執(zhí)行相對來說代價較高的反序列化步驟之前拒絕不符合架構(gòu)的消息。  請注意,本示例在 WebMethod 體中驗證消息。這樣做是為了簡單。無論在什么位置,驗證消息的步驟都是相同的。有關(guān) SOAP 擴展中的驗證的更多信息,請參考以下 MSDN article(MSDN 文章)。  [WebService(Namespace = "http:///")] [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; } }  六 引發(fā)帶有自定義信息的 Soap 異常的 ASP.NET Web 服務(wù) 服務(wù)器可以使用 SoapException 將自定義錯誤信息發(fā)送到客戶端。引發(fā)(但未捕獲)SoapException 以后,服務(wù)器以 SOAP 錯誤的形式在網(wǎng)絡(luò)上發(fā)送錯誤信息。該 SOAP 錯誤在客戶端上被反序列化回 SoapException。在 SOAP 錯誤的 Detail 元素中發(fā)送自定義(計算機可讀的)錯誤信息。一個 SOAP 錯誤還包括一條可以人讀的錯誤信息、一個錯誤代碼和一個可選的 SOAP actor。 示例代碼: 服務(wù)端: [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 服務(wù)對 SOAP 標(biāo)頭的支持。該示例使用一個授權(quán)標(biāo)頭,該標(biāo)頭與含有用戶名/密碼信息的請求一起發(fā)送。第一次調(diào)用 WebMethod 時未包括 SOAP 標(biāo)頭,因此失敗。第二次調(diào)用 WebMethod 時包括 SOAP 標(biāo)頭,因此成功返回。  Sample Code: 服務(wù)端 /**//// <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:///")] [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 "錯誤: 請?zhí)峁┥矸輵{據(jù)"; 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))//可能是查詢數(shù)據(jù)庫 ...{ 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>"); 客戶端執(zhí)行結(jié)果如下:  Using Soap Headers for Custom Authentication First call result without SOAP Header: 錯誤: 請?zhí)峁┥矸輵{據(jù) Second call result with SOAP Header:  成功  八 UseDefaultCredentials 功能的簡單 Web 服務(wù) 對于客戶端代理類的實例來說,如果將 UseDefaultCredentials 屬性設(shè)置為 true,則客戶端將使用默認憑據(jù)對 Web 服務(wù)進行身份驗證。例如:  UseDefaultCredentialsService service = new UseDefaultCredentialsService(); service.UseDefaultCredentials = true; 將 UseDefaultCredentials 屬性設(shè)置為 true 等效于下列代碼行 service.Credentials = System.Net.CredentialCache.DefaultCredentials; 同時,還需要在站點部署后在IIS中去掉服務(wù)端匿名訪問,允許Windows集成身份驗證。 總結(jié): 本次練習(xí)主要參考ASPNET2.0的QuickStart示例,學(xué)習(xí)了Web 服務(wù)調(diào)用,會話狀態(tài)的使用,同步、異步調(diào)用,驗證,授權(quán),異常。以及WSDL.exe的常見用法。 本文來自CSDN博客,轉(zhuǎn)載請標(biāo)明出處:http://blog.csdn.net/themoment_rain/archive/2006/12/20/1450562.aspx | 
|  |