现在的位置: 首页 > 综合 > 正文

C#WebService 之Session之我见

2013年12月08日 ⁄ 综合 ⁄ 共 7874字 ⁄ 字号 评论关闭

        这几天一直在学习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

抱歉!评论已关闭.