C#WebService 之Session之我见

来源:互联网 发布:php微信商城源码下载 编辑:程序博客网 时间:2024/04/28 00:25

        这几天一直在学习WebService的知识。正好现在有一个项目,需要在WebService实现如下接口: 

String Login(string username, string password) // 登录方法,返回值用来指名是不是登录成功,并且这个值在之后的接口中用来找到相对应的服务器上的session。

       因此WebService需要使用到Session,而网上大部分资料是说WebService是无状态的(StateLess),不怎么支持Session。因此难题出现了,首先在Web Serivice

放上声明如下Attribute,[WebMethod(EnableSession = true)],此为表示在webService上能使用Session。

      现在放上我写的WebService的例子代码(service端):

    /// <summary>    /// Summary description for Service1    /// </summary>    [WebService(Namespace = "http://tempuri.org/")]    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]    [System.ComponentModel.ToolboxItem(false)]    // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.     [System.Web.Script.Services.ScriptService]    public class Bussiness : System.Web.Services.WebService    {                [WebMethod(Description = "登录方法,返回值用来指名是不是登录成功,并且这个值在之后的接口中用来找到相对应的服务器上的session",            EnableSession = true)]        public string Login(string username, string password)        {            string state = "";            if (IsLogin(username))                state = "Logined";            else            {                state = UserHelper.Login(username, password);                if (state != null && state != "Failed")//                {                    //Session.Timeout = 1;                    Session[state] = username;                }            }            return state;        }        [WebMethod(Description = "判断是否登录",          EnableSession = true)]        private  bool  IsLogin(string name)        {            if (name != null &&  Session[name]!=null&& Session[name].ToString() == name)                return true;            return false;        }

 客户端代码,我用的是soap方式写的,soap方式調用WebService的方法,我参看了《Programing Web Service with SOAP》。具体方式参看第三章的。我的客户端SOAP代码(我新建一个类)如下:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Diagnostics;using System.Web.Services;using System.Web.Services.Protocols;using System.Xml.Serialization;namespace Test{    [WebServiceBinding(Name = "BusServiceSoap", Namespace = "http://tempuri.org/")]    public class BusService : SoapHttpClientProtocol    {        public BusService()        {            // this.Url = "http://localhost:4243/Bussiness.asmx";             this.Url = "http://localhost/Bussiness/Bussiness.asmx";        }         [System.Web.Services.Protocols.SoapDocumentMethod(            "http://tempuri.org/Login",            RequestNamespace = "http://tempuri.org/",            ResponseNamespace = "http://tempuri.org/",            Use = System.Web.Services.Description.SoapBindingUse.Literal,            ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]        public string Login(string username, string password)        {            object[] result = this.Invoke("Login",                                            new object[] { username, password });            return (string)result[0];        }    }}


客户点調用代码,也就是用户端的調用代码,我写的是控制台的测试代码,如下:

namespace Test{    public class Program    {        static void Main(string[] args)        {            string name = "admin";            string password = "123";            TestLogin tl = new TestLogin(name, password);                        string state = tl.Login();            Console.WriteLine("State = " + state);            state = tl.Login();            Console.WriteLine("State = " + state);            Console.Read();        }    }    public class TestLogin    {        public string name = "";        public string psw = "";        BusService bus = new BusService();        public TestLogin(string name, string psw)        {                     this.name = name;            this.psw = psw;          }        public string Login()        {            return bus.Login(this.name, this.psw);        }    }     }

写到这里进行运行,感觉一切应该按照自己想想的正确的打印出来。打印结果应该是如下这样的:

State = admin

State = Logined

结果实际运行的效果与自己设想的不太一样,实际运行的结果是

State = admin

State = admin

这样的运行结果说明,WebService 的Server端的Session,根本没有保存。通过断点调试发现,第二次读取的Session为空,就是没有保存。

因此只在Server端进行声明EnableSession = true,是不够的,这只是说明Server端现在能用session了。

经过上网查阅资料得知:要想使用Session,在进行上一步的声明之后,还要在客户端实例话WebService对象时,对其CookieContainer也要进行初始化方可使用Session的存储状态。另外在多个webservice代理中,只要含有相同的cookie,就能共用相同的session,其中的cookie通过代理类的CookieContainer.GetCookies(new Uri(s.Url))["ASP.NET_SessionId"]取得,如果其他的webserivce代理类需要用相同的session则可以用CookieContainer.Add方法,将取得的cookie加入即可(还没进行测试)。

知道了如何使用后,修改客户端的Soap代码即可,修改后的代码如下:

    [WebServiceBinding(Name = "BusServiceSoap", Namespace = "http://tempuri.org/")]    public class BusService : SoapHttpClientProtocol    {        private static  System.Net.CookieContainer cookieContainer;        static BusService()        {            cookieContainer = new System.Net.CookieContainer();        }        public BusService()        {             this.Url = "http://localhost:4243/Bussiness.asmx";             this.CookieContainer = new System.Net.CookieContainer();          /// this.Url = "http://localhost/Bussiness/Bussiness.asmx";        }         [System.Web.Services.Protocols.SoapDocumentMethod(            "http://tempuri.org/Login",            RequestNamespace = "http://tempuri.org/",            ResponseNamespace = "http://tempuri.org/",            Use = System.Web.Services.Description.SoapBindingUse.Literal,            ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]        public string Login(string username, string password)        {            object[] result = this.Invoke("Login",                                            new object[] { username, password });            return (string)result[0];        }    }

修改完了之后,进行测试,测试结果与设想的结果一样。

本文的一些内容出自http://63542424.blog.163.com/blog/static/18883900201161632532355/

PS:新手学习WebService的拙见,还望高手给出意见,或者推荐一些webService相关的经典书籍,小生在此不胜感激。

 

上面的soap端写的代码似乎还是有写问题,原因就是cookieContainer对象可能不一致,会导致服务端Session丢失。改进策略是基于单例模式的设计模式的方法进行修改的,修改的代码如下,这样就可以保证在程序中使用相同的CookieContainer进而保证Session不会意外丢失。

 

namespace Test{    [WebServiceBinding(Name = "BusServiceSoap", Namespace = "http://tempuri.org/")]    public class BusService : SoapHttpClientProtocol    {        private static  System.Net.CookieContainer cookieContainer;        private static BusService instance;        static BusService()        {            cookieContainer = new System.Net.CookieContainer();            instance = new BusService();            instance.CookieContainer = cookieContainer;        }        private BusService()        {             this.Url = "http://localhost:4243/Bussiness.asmx";             //this.CookieContainer = new System.Net.CookieContainer();                        //this.Url = "http://localhost/Bussiness/Bussiness.asmx";        }        public static BusService getInstance()        {            if (instance == null)                instance = new BusService();            return instance;        }         [System.Web.Services.Protocols.SoapDocumentMethod(            "http://tempuri.org/Login",            RequestNamespace = "http://tempuri.org/",            ResponseNamespace = "http://tempuri.org/",            Use = System.Web.Services.Description.SoapBindingUse.Literal,            ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]        public string Login(string username, string password)        {            object[] result = this.Invoke("Login",                                            new object[] { username, password });            return (string)result[0];        }        [System.Web.Services.Protocols.SoapDocumentMethod(            "http://tempuri.org/AnalyzePrescription",            RequestNamespace ="http://tempuri.org/",            ResponseNamespace = "http://tempuri.org/",            Use = System.Web.Services.Description.SoapBindingUse.Literal,            ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped        )]        public int AnalyzePrescription(string name, List<Student> message)        {            object[] results = this.Invoke("AnalyzePrescription",new object[]{name,message});            return (int)results[0];        }        [System.Web.Services.Protocols.SoapDocumentMethod(            "http://tempuri.org/IsFinishedAnalysis",            RequestNamespace = "http://tempuri.org/",            ResponseNamespace = "http://tempuri.org/",            Use = System.Web.Services.Description.SoapBindingUse.Literal,            ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped        )]        public bool IsFinishedAnalysis(string name, int postion)        {            object[] results = this.Invoke("IsFinishedAnalysis", new object[] { name, postion });            return (bool)results[0];        }        [System.Web.Services.Protocols.SoapDocumentMethod(            "http://tempuri.org/GetAnalyzedResult",            RequestNamespace = "http://tempuri.org/",            ResponseNamespace = "http://tempuri.org/",            Use = System.Web.Services.Description.SoapBindingUse.Literal,            ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped        )]        public Result GetAnalyzedResult(string name, int postion)        {            object[] results = this.Invoke("GetAnalyzedResult", new object[] { name, postion });            return (Result)results[0];        }        [System.Web.Services.Protocols.SoapDocumentMethod(                    "http://tempuri.org/Release",                    RequestNamespace = "http://tempuri.org/",                    ResponseNamespace = "http://tempuri.org/",                    Use = System.Web.Services.Description.SoapBindingUse.Literal,                    ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped                )]        public bool Release(string name, int postion)        {            object[] results = this.Invoke("Release", new object[] { name, postion });            return (bool)results[0];        }        [System.Web.Services.Protocols.SoapDocumentMethod(                    "http://tempuri.org/LoginOut",                    RequestNamespace = "http://tempuri.org/",                    ResponseNamespace = "http://tempuri.org/",                    Use = System.Web.Services.Description.SoapBindingUse.Literal,                    ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped                )]        public bool LoginOut(string name)        {            object[] results = this.Invoke("Release", new object[] { name });            return (bool)results[0];        }    }}



PS :单例模式(Singleton)学习的文章:  http://blog.csdn.net/wziyx513225244/article/details/6649652