0%

使用C#开发WebService接口

由于工作需求,不得已要做一些业务接口,使用C#语言和Visual Studio2010开发完成。一开始真的完全不懂如何下手,慢慢的从网上查找一些这方面的资料,一步步地到现在可以自己独立完成接口的开发,其中也是经历了挺多挫折的。现在希望能够分享一下这方面的东西,也是为以后做个笔记吧。

Step1.创建WebService项目

1. 首先我们打开Visual Studio2010开发工具,点击导航栏—文件—新建项目,选择Visual C#–Web,选择ASP.NET空Web应用程序,项目名称可以随意定,点击确定。

2. 打开解决方案管理器,找到我们刚才创建的那个项目,右键—添加新建项,选择Web服务,名称也是由自己定,确定后就完成了项目的创建。

代码解析

我们双击打开后缀名为.asmx的文件,看到如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
namespace WebApplication2
{
/// <summary>
/// WebService1 的摘要说明
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
// 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消对下行的注释。
// [System.Web.Script.Services.ScriptService]
public class WebService1 : System.Web.Services.WebService
{

[WebMethod]
public string HelloWorld()
{
return "Hello World";
}
}
}

这是开发工具自动帮我们生成的初始代码的demo,我们主要关注的是HelloWord这个方法,如果一个方法上面带有[WebMethod],则说明此方法是对外公开,可供外部调用的,说白了,这就是我们的接口,如果我们想对该方面写注释要怎么做呢?只需要把[WebMethod]改为[WebMethod(Description=”这是外部调用的接口”)],这样里面的中文说明在我们启动项目的时候就可以看到了。

Step2.项目代码的结构

上面我们已经创建好了项目,下面根据业务开始设计代码的结构,一个好的结构可以让我们更好地维护项目。现在以最近做的一个项目为例子,只是我自己设计的,可以根据自己的实际情况设计结构,接口的传入数据、返回数据都为xml格式。

我先讲解我的接口业务,涉及到查询数据、新增记录等,例如我们常见的 挂号,我就以挂号接口作为一个例子讲解实际业务。外部调用接口,传入必需的挂号相关信息,如订单号、号别、时段、挂号人信息、支付金额等,而我们的接口需要将这些传入的数据作为依据,查找是否存在对应的号源,如果信息无误,则完成挂号的操作,并且返回相应的订单信息给接口调用者。

那么我们确定好接口的传入参数是xml格式的字符串,返回的数据也是xml格式的字符串,如果要对这些数据进行操作,最好的办法就是把xml格式的字符串转化为类,使用一个泛型类将其序列化类,确定好数据的处理,下面我们开始设计结构。

下面是我设计的代码结构:

TJYD.Helper ——–存放工具类,例如我们刚才提到的序列化类

application ——–创建的项目

appliaction.Business ——-数据处理类,主要完成入参和出参的数据处理

application.Business.DAL ——-Model层,负责跟数据库交互

application.Business.Request ——–请求入参处理类

application.Business.Response ———返回数据处理类

Step3.代码实例

我们以一个实例来解释代码逻辑处理的过程。

1.接口代码

1
2
3
4
5
6
7
8
[WebMethod(Description = "号源信息查询")]
public string getRegInfo(string xml)
{
string response = "";
Business.Clinic.clinicBusiness.getClinicSource(xml,ref response);
return response;
}

注释:ref是对实例的引用,类似指针的作用。

1.数据处理类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
 #region [ 号源信息 ]
public static void getClinicSource(string requestXml, ref string response)
{
XmlHelper<Request.Clinic.getClinicSourceRequest> requestHelper = new XmlHelper<Request.Clinic.getClinicSourceRequest>();
XmlHelper<Response.Clinic.getClinicSourceResponse> responseHelper = new XmlHelper<Response.Clinic.getClinicSourceResponse>();

Response.Clinic.getClinicSourceResponse br = new Response.Clinic.getClinicSourceResponse();
br.clinicSourceResult = new Response.Clinic.clinicSourceResult();
br.clinicSourceResult.clinicSourceCollection = new List<Response.Clinic.clinicSourceCollection>();

//每天号源
Dictionary<string, List<YY_SG_WebService.Business.Response.Clinic.clinicSourceItem>> scheduleDateDic = new Dictionary<string, List<Response.Clinic.clinicSourceItem>>();

var request = requestHelper.Deserialize(requestXml);
if (request != null)
{
BLL.Clinic.clinicBLL bll = new BLL.Clinic.clinicBLL();
bool isError = false;
string ErrorMessage = "";
string resultCode = "";
var ds = bll.getClinicSource(request.clinicSource.branchCode, request.clinicSource.beginDate, request.clinicSource.endDate, request.clinicSource.deptCode, request.clinicSource.doctorCode, ref isError, ref ErrorMessage,ref resultCode);
bool isData = true;
//判断是否返回数据
if (ds.Tables[0].Columns.Contains("resultMessage"))
{
isData = false;
}
if (ds.Tables.Count > 0 && isData)
{
for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
{
var dr = ds.Tables[0].Rows[i];
var date = dr["scheduleDates"].ToString();
YY_SG_WebService.Business.Response.Clinic.clinicSourceItem item = null;

if (scheduleDateDic.ContainsKey(date))
{
//在字典里面查找号源
item = scheduleDateDic[date].FirstOrDefault(d => d.doctorNo == dr["doctorNo"].ToString());
if (item == null)
{
item = new Response.Clinic.clinicSourceItem();
item.category = dr["category"].ToString();
item.deptCode = dr["deptCode"].ToString();
item.deptName = dr["deptName"].ToString();
item.doctorCode = dr["doctorNo"].ToString();
item.doctorNo = dr["doctorNo"].ToString();
item.doctorName = dr["doctorName"].ToString();
item.doctorSex = dr["doctorSex"].ToString();
item.doctorTelephone = dr["doctorTelephone"].ToString();
item.doctorSkill = dr["doctorSkill"].ToString();
item.doctorIntroduction = dr["doctorIntroduction"].ToString();
item.doctorTitle = dr["doctorTitle"].ToString();
item.picture = dr["picture"].ToString();
item.leftTotalNum = dr["leftTotalNum"].ToString();
item.clinicSourceDetail = new List<Response.Clinic.clinicSourceDetail>();
scheduleDateDic[date].Add(item);
}
}
else
{
item = new Response.Clinic.clinicSourceItem();
item.category = dr["category"].ToString();
item.deptCode = dr["deptCode"].ToString();
item.deptName = dr["deptName"].ToString();
item.doctorCode = dr["doctorNo"].ToString();
item.doctorNo = dr["doctorNo"].ToString();
item.doctorName = dr["doctorName"].ToString();
item.doctorSex = dr["doctorSex"].ToString();
item.doctorTelephone = dr["doctorTelephone"].ToString();
item.doctorSkill = dr["doctorSkill"].ToString();
item.doctorIntroduction = dr["doctorIntroduction"].ToString();
item.doctorTitle = dr["doctorTitle"].ToString();
item.picture = dr["picture"].ToString();
item.leftTotalNum = dr["leftTotalNum"].ToString();

item.clinicSourceDetail = new List<Response.Clinic.clinicSourceDetail>();

scheduleDateDic.Add(date, new List<Response.Clinic.clinicSourceItem> { item });
}


var detail = item.clinicSourceDetail.FirstOrDefault(d => d.timeFlag == dr["timeFlags"].ToString());
//时间段不存在,添加时间段
if (detail == null)
{
detail = new Response.Clinic.clinicSourceDetail();
detail.timeFlag = dr["timeFlags"].ToString();
detail.hasDetailTime = "1";
detail.beginTime = dr["beginTime"].ToString();
detail.endTime = dr["endTime"].ToString();
detail.workStatus = "1";
detail.totalNum = dr["totalNum"].ToString();
detail.leftNum = dr["leftTotalNum"].ToString();
detail.regFee = dr["regFee"].ToString();
detail.treatFee = dr["treatFee"].ToString();
detail.workId = "";
item.clinicSourceDetail.Add(detail);
}

}
foreach (var date in scheduleDateDic.Keys)
{
Response.Clinic.clinicSourceCollection item = new Response.Clinic.clinicSourceCollection();
item.scheduleDate = date;
item.clinicSourceItem = scheduleDateDic[date];

br.clinicSourceResult.clinicSourceCollection.Add(item);
}
}
else
{
br.resultCode = resultCode;
br.resultMessage =ds.Tables[0].Rows[0]["resultMessage"].ToString();
}
br.resultCode = resultCode;
}
else
{
br.resultCode = "-1";
br.resultMessage = "传入参数不正确或者为空";
}

response = responseHelper.Serialize(br);
}

上面最开始我们用到了泛型类,生成了两个实例类,这两个类是根据入参出参构造出来的。

入参类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
namespace YY_SG_WebService.Business.Request.Clinic
{
[XmlRoot(ElementName = "request")]
[Serializable]
public class getClinicSourceRequest : BaseRequest
{
[XmlElement("params")]
public clinicSource clinicSource { get; set; }

}
public class clinicSource
{
public string branchCode { get; set; }
public string beginDate { get; set; }
public string endDate { get; set; }
public string deptCode { get; set; }
public string doctorCode { get; set; }
}
}
出参类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
namespace YY_SG_WebService.Business.Response.Clinic
{
[XmlRoot(ElementName = "response")]
[Serializable]
public class getClinicSourceResponse:BaseResponse
{
[XmlElement("result")]
public clinicSourceResult clinicSourceResult { get; set; }
}
public class clinicSourceResult
{
[XmlElement("collection")]
public List<clinicSourceCollection> clinicSourceCollection { get; set; }
}
public class clinicSourceCollection
{
public string scheduleDate { get; set; }
[XmlElement("item")]
public List<clinicSourceItem> clinicSourceItem { get; set; }
}
public class clinicSourceItem
{
public string category { get; set; }
public string deptCode { get; set; }
public string deptName { get; set; }
public string doctorCode { get; set; }
public string doctorNo { get; set; }
public string doctorName { get; set; }
public string doctorSex { get; set; }
public string doctorTelephone { get; set; }
public string doctorSkill { get; set; }
public string doctorIntroduction { get; set; }
public string doctorTitle { get; set; }
public string picture { get; set; }
public string leftTotalNum { get; set; }
[XmlElement("detail")]
public List<clinicSourceDetail> clinicSourceDetail { get; set; }
}
public class clinicSourceDetail
{
public string timeFlag { get; set; }
public string hasDetailTime { get; set; }
public string beginTime { get; set; }
public string endTime { get; set; }
public string workStatus { get; set; }
public string totalNum { get; set; }
public string leftNum { get; set; }
public string regFee { get; set; }
public string treatFee { get; set; }
public string workId { get; set; }
}
}

上面是我实际的业务构造的类,比较复杂,看实际情况构造,这里涉及到了C#的xml相关知识,具体可百度了解。

我们看到上面的数据处理类,关注的重点是 **bll.getClinicSource()**方法,由这个方法调用我们跟数据库交互的方法,然后返回DataSet(该数据为接口返回的业务数据),后面是对返回的业务数据根据约定的格式进行处理封装,responseHelper.Serialize这个方法是将返回业务数据类反序列化为xml格式字符串。其中由于返回的数据格式较为复杂,有四个层级,使用了Dictionary进行存储分类,再赋值给实例类。

数据库交互类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public DataSet getClinicSource(string branchCode, string  beginDate, string  endDate, string deptCode, string doctorCode, ref bool isError, ref string ErrorMessage,ref string resultCode)
{
List<OracleParameter> paramList = new List<OracleParameter>();
paramList.Add(DBHelper.createParameter("branchCode", 30, ParameterDirection.Input, branchCode));
paramList.Add(DBHelper.createParameter("beginDate", 30, ParameterDirection.Input, beginDate));
paramList.Add(DBHelper.createParameter("endDate", 30, ParameterDirection.Input, endDate));
paramList.Add(DBHelper.createParameter("deptCode", 30, ParameterDirection.Input,deptCode));
paramList.Add(DBHelper.createParameter("doctorCode", 30, ParameterDirection.Input, doctorCode));
paramList.Add(DBHelper.createParameter("curout", ParameterDirection.Output, OracleType.Cursor));
paramList.AddRange(DBHelper.CreateBaseParameter());
OracleParameter[] pm = paramList.ToArray();
DataSet ds = new DataSet();
try
{
ds = DBHelper.runProc_Ret_DataSet("proc_clinic_Info", ref pm);
foreach (var op in pm)
{
if (op.ParameterName == "resultMessage")
{
ErrorMessage = op.Value.ToString();
}
if (op.ParameterName == "resultCode")
{
resultCode = op.Value.ToString();
}
}
isError = false;
}
catch (Exception e)
{
isError = true;
ErrorMessage = e.Message;
TJYD.Helper.Logger.Write("proc_clinic_Info," + e.Message);
}
return ds;
}

DBHelper.runProc_Ret_DataSet该方法是调用数据库的存储过程,第一个参数是存储过程名称,第二个是存储过程入参,返回DataSet。

思绪有点凌乱,先写到这吧,有些东西想说清楚,但是又没法整理好逻辑关系,头疼(—)