WebServiceWCF

    技术2022-05-19  21

    (一)如何发布WebService呢?使网络中其它机器能使用我的WebService

     

    我写了一个简单的WebService,在本机上测试没有问题。  但网络中其它机器访问我的WebService时,提示“该调用只能用于本地测试”   修改web.config配置文件  

    < System.Web >       < webServices >        < protocols >      < add  name = " HttpGet " />      < add  name = " HttpPost " />    </ protocols >      </ webServices >    </ System.Web >  

     

    (二)WebService/WCF Session Cookie

     

    在.net 3.0推出WCF之前使用的WebService,有的应用有使用Session保持一些信息,在不同的WebMethod中共享存储信息。比如:保持登陆用户的信息等。其原理是应用ASP.NET兼容模式,利用HttpContext来保持请求的上下文。        为了显示WebService/WCF不同应用下的Session/Cookie应用,这里分别创建两个Service应用:一个是WebService Application(.net 4.0下没有此模板,只有在.net 3.5以下版本中有),一个是WCFService Application(IIS宿主的WCF应用)1. WebService Application(*.asmx) + .net 2.0 Client Proxy可以看到 Login 方法里将登录的 userName 保存在 Session 里。在 GetUserName 方法返回 Session 中的数据。view plaincopy to clipboardprint?[WebService(Namespace = "http://tempuri.org/")]   [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]   [System.ComponentModel.ToolboxItem(false)]   public class Service1 : System.Web.Services.WebService   {       [WebMethod(EnableSession=true)]       public void Login(string user)       {           var session = HttpContext.Current.Session;           session["user"] = user;           HttpContext.Current.Response.Cookies.Add(new HttpCookie("user", user));       }       [WebMethod(EnableSession = true)]       public string GetUserName()       {           return HttpContext.Current.Session["user"] as string;       }   }  [WebService(Namespace = "http://tempuri.org/")][WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)][System.ComponentModel.ToolboxItem(false)]public class Service1 : System.Web.Services.WebService{    [WebMethod(EnableSession=true)]    public void Login(string user)    {        var session = HttpContext.Current.Session;        session["user"] = user;        HttpContext.Current.Response.Cookies.Add(new HttpCookie("user", user));    }    [WebMethod(EnableSession = true)]    public string GetUserName()    {        return HttpContext.Current.Session["user"] as string;    }} 先来看看 .net 2.0 中的客户端如何保持 Session 的。ASP.NET 中的客户端也就是浏览器端会通过Cookie来保持 Session。所以对于 WebService 的客户端需要自己去维护一个 CookieContainer。(服务端需要没一个WebMethod都需要设定EnableSession=true)view plaincopy to clipboardprint?CookieContainer cookieContainer = new CookieContainer();  CookieContainer cookieContainer = new CookieContainer(); 而每次调用都必须添加这个cookieContainer的实例。PS: .net 3.5里仍然可以使用.net 2.0生成客户端:Add Service Reference -> Advance -> Add Web Reference

    添加完WebService Reference后客户端调用:view plaincopy to clipboardprint?using (var svc = new MyWebSvc.Service1())   {       svc.CookieContainer = cookieContainer;       svc.Login(textBox1.Text);   }  using (var svc = new MyWebSvc.Service1()){    svc.CookieContainer = cookieContainer;    svc.Login(textBox1.Text);} 再一次调用:view plaincopy to clipboardprint?using (var svc = new MyWebSvc.Service1())   {       svc.CookieContainer = cookieContainer;       label1.Text = svc.GetUserName();   }  using (var svc = new MyWebSvc.Service1()){    svc.CookieContainer = cookieContainer;    label1.Text = svc.GetUserName();} OK,现在的客户端实现了cookie的保持,每次调用Service方法时,Service会携带之前的cookie信息,则在服务端则能识别调用的Session而返回对应的数据。

    2. WebService Application(*.asmx) + .net 3.5 Client Proxy服务端代码没有变化,客户端引用则修改为 Add Service Reference .net 3.5 生成客户端代理。这次生成的客户端代理中已经找不到 svc 中的 CookieContainer 属性,难道不能保持客户端 cookie 了吗?检查客户端生成 app.config (.net 3.5里的WebService原来使用的是basicHttpBinding)<system.serviceModel>        <bindings>            <basicHttpBinding>                <binding name="Service1Soap" allowCookies="false" ......原来 allowCookies 默认设为 false 了,我们把它改为:true 就OK了。view plaincopy to clipboardprint?using (var svc = new MyWCFWebSvc.Service1SoapClient())   {       svc.Login(textBox1.Text);   }  using (var svc = new MyWCFWebSvc.Service1SoapClient()){    svc.Login(textBox1.Text);} 再次调用:view plaincopy to clipboardprint?using (var svc = new MyWCFWebSvc.Service1SoapClient())   {       label1.Text = svc.GetUserName();   }  using (var svc = new MyWCFWebSvc.Service1SoapClient()){    label1.Text = svc.GetUserName();}

    3. WCF Service Application(*.svc) + .net 3.5 Client ProxyWCF的ServiceContractview plaincopy to clipboardprint?[ServiceContract]   public interface IService1   {       [OperationContract]       string GetUserName();       [OperationContract]       void Login(string user);   }  [ServiceContract]public interface IService1{    [OperationContract]    string GetUserName();    [OperationContract]    void Login(string user);}Service的实现,类似上面的WebMethodview plaincopy to clipboardprint?[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]   public class Service1 : IService1   {       public void Login(string user)       {           var session = HttpContext.Current.Session;           session["user"] = user;           HttpContext.Current.Response.Cookies.Add(new HttpCookie("user", user));       }       public string GetUserName()       {           return HttpContext.Current.Session["user"] as string;       }   }  [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]public class Service1 : IService1{    public void Login(string user)    {        var session = HttpContext.Current.Session;        session["user"] = user;        HttpContext.Current.Response.Cookies.Add(new HttpCookie("user", user));    }    public string GetUserName()    {        return HttpContext.Current.Session["user"] as string;    }} WCF Service Application的工程模板中,默认是没有启用ASP.NET兼容模式的,这个时候直接调用 HttpContext 将返回 null。所以需要设置 AspNetCompatibilityRequirements 特性:1)[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]2)服务端配置文件也需要修改,在 <system.serviceModel> 节点中,添加如下配置:<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>客户端生成的配置文件 app.config 也同样需要设置

    <system.serviceModel>        <bindings>              <wsHttpBinding>                  <binding name="WSHttpBinding_IService1" allowCookies="true" ......

    运行效果:

     

    上面的代码中,cookie只在应用程序的生存周期内有效,也就是说当程序关闭,cookie就失效了。服务端也就不能取得对应的session信息了。如果一定要实现类似浏览器浏览网页,今天登陆明天再开还能有效呢?那就得自己来维持这个CookieContainer了,也就是说持久化这个对象。不过遗憾的是在.net3.0以上版本直接添加Service Reference的本地代理中,并没有CookieContainer属性。只能选择使用.net2.0生成客户端代理。持久化CookieContainer的代码如下: view plaincopy to clipboardprint?CookieContainer cookieContainer = new CookieContainer();   private void Form1_Load(object sender, EventArgs e)   {       var cookieFile = "MyCookie.dat";       if (File.Exists(cookieFile))       {           using (var fs = File.OpenRead(cookieFile))           {               var bf = new BinaryFormatter();               cookieContainer = bf.Deserialize(fs) as CookieContainer;           }       }   }   private void Form1_FormClosing(object sender, FormClosingEventArgs e)   {       var cookieFile = "MyCookie.dat";       using (var fs = File.OpenWrite(cookieFile))       {           var bf = new BinaryFormatter();           bf.Serialize(fs, cookieContainer);       }   }  CookieContainer cookieContainer = new CookieContainer();private void Form1_Load(object sender, EventArgs e){    var cookieFile = "MyCookie.dat";    if (File.Exists(cookieFile))    {        using (var fs = File.OpenRead(cookieFile))        {            var bf = new BinaryFormatter();            cookieContainer = bf.Deserialize(fs) as CookieContainer;        }    }}private void Form1_FormClosing(object sender, FormClosingEventArgs e){    var cookieFile = "MyCookie.dat";    using (var fs = File.OpenWrite(cookieFile))    {        var bf = new BinaryFormatter();        bf.Serialize(fs, cookieContainer);    }}

     

    出处:http://blog.csdn.net/fangxinggood/archive/2011/04/19/6332489.aspx


    最新回复(0)