多WebService的状态同步以及实现WebService基类
WebService非常轻量,基于SOAP,在做客户端程序的时候,可以借助VS的自动生成代理类,相比较于Web Api还需要自己手写访问代码省了很多事情,做一些小型的和简单的服务非常方便。之前使用WebService的时候都是用一个asmx文件,将所有代码揉在一个文件里,代码写多了,看的有点头大。今天就试着将这些代码拆分一下,在一个Web项目里,创建多个asmx文件,为了便于共用代码,需要有一个基类,其它的WebService类均从这个基类派生;另一个也同时测试下多个asmx的cookie是否能同步。
1、首先在VS中搭建项目结构,首先建立一个空白解决方案,我将这个空白解决方案取名为“WebServiceTest”;
2、然后依次添加2个项目,项目名和类型如下所示;
项目名称 | 项目类型 |
Services | 空白的Asp.net Web应用程序项目 |
Client | Windows窗体应用程序 |
项目结构最后的效果如下:
3、接下来在Services项目中新建类文件:BaseService.cs。
注意不要建成了asmx文件,同时将其声明为abstract,否则在Client项目里引用的时候,会将这个BaseService识别为一个独立的WebService;
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Services; namespace Services { public abstract class BaseService : WebService { [WebMethod(EnableSession = true)] public string CurrentUser() { return Context.Session["CurrentUser"]?.ToString(); } } }
4、接下来新建一个WebService文件:UserService.asmx,该WebService继承自BaseService,模拟一个简单的登录效果,其代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Services; namespace Services { /// <summary> /// Service1 的摘要说明 /// </summary> [WebService(Namespace = "http://tempuri.org/User")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] [System.ComponentModel.ToolboxItem(false)] // 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消注释以下行。 // [System.Web.Script.Services.ScriptService] public class UserService : BaseService { [WebMethod(EnableSession = true)] public bool Login(string name, string pwd) { if (AppContext.LoginUsers.Contains(name)) { Context.Session["CurrentUser"] = name; return true; } if (AppContext.Users.Keys.Contains(name) && AppContext.Users[name] == pwd) { AppContext.LoginUsers.Add(name); Context.Session["CurrentUser"] = name; return true; } return false; } [WebMethod(EnableSession =true)] public void LogOut() { string name = Session["CurrentUser"]?.ToString(); if (!string.IsNullOrEmpty(name) && AppContext.LoginUsers.Contains(name)) { AppContext.LoginUsers.Remove(name); } Session["CurrentUser"] = null; } } }
5、新建一个AppContext文件,用于模拟所有用户信息,并用于存储当前所有登录用户的信息,代码如下所示:
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace Services { public class AppContext { public static Dictionary<string,string> Users = new Dictionary<string, string>() { { "user1","111"}, { "user2","111"}, { "alexywt","111"} }; public static List<string> LoginUsers = new List<string>(); } }
6、再添加一个WebService文件:TestService.asmx,这个文件只是为了检验2个不同的WebService可以共用同一session、cookie而设,不需要再添加任何方法,直接使用继承自BaseService的方法验证即可,代码如下;
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Services; namespace Services { /// <summary> /// TestService 的摘要说明 /// </summary> [WebService(Namespace = "http://tempuri.org/Test")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] [System.ComponentModel.ToolboxItem(false)] // 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消注释以下行。 // [System.Web.Script.Services.ScriptService] public class TestService : BaseService { } }
7、在Client项目中的窗体中添加3个按钮,1个文本框,界面如下所示;
对象 | 描述 |
文本框 | 输入登录用户名 |
“登录”按钮 | 调用UserService的Login方法进行登录操作 |
“退出”按钮 | 调用UserService的LogOut方法进行退出操作 |
“查看”按钮 | 调用TestService的CurrentUser方法获取当前用户,并显示 |
窗体的代码如下:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Net; using System.Text; using System.Windows.Forms; namespace Client { public partial class Form1 : Form { private static CookieContainer cookieBox = new CookieContainer(); private UserServiceRef.UserService userService; private TestServiceRef.TestService testService; public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { string name = textBox1.Text; if (string.IsNullOrEmpty(name)) return; userService = new UserServiceRef.UserService(); userService.CookieContainer = cookieBox; userService.Credentials = CredentialCache.DefaultCredentials; userService.Login(name, "111"); name = userService.CurrentUser(); MessageBox.Show(name); } private void button2_Click(object sender, EventArgs e) { testService = new TestServiceRef.TestService(); testService.CookieContainer = cookieBox; testService.Credentials = CredentialCache.DefaultCredentials; string name = testService.CurrentUser(); MessageBox.Show(name); } private void button3_Click(object sender, EventArgs e) { if (userService == null) return; userService.LogOut(); } } }
8、先将2个项目编译一下,然后只启动Web项目Services,在Client项目的“\bin\Debug”目录下,运行“client.exe”三次,打开3个客户端,分别输入账号,并登录,分别点击查看,得到3个不同的用户名,点击其中1个退出按钮,再点击3个查看按钮,可以发现只有当前客户端退出了,另2个客户端没有影响,说明对于同一个Client程序,cookie没有影响。