在 .NET/C# 中构建基于 ReST 的 Web 服务





5.00/5 (11投票s)
一个用于 C# 的基于 ReST 的 Web 服务。
引言
网上有各种 ReST 示例,例如 .NET/C# 的 Web 服务,但它们都没有提供一个简单的 .NETish 框架。 例如,通过仅从一个类派生并注释方法作为 Web 暴露,创建 Web 服务有多容易? 本文提供了一个用于基于 ReST 的 Web 服务的简单框架,主要针对 .NET 版本 3.5 和更早版本。
使用代码
与网上关于 ReST 和 .NET 的任何其他文章一样,此实现涉及通过 IHttpHandler
处理特定的资源请求; 在这种情况下,它是 PoC.Web.Services.ReSTServiceHandler
。 这个 IHttpHandler
将处理 ReST 调用(Get、Put、Post 和 Delete)并适当地分发它们。 为了添加处理程序,必须将以下行添加到 web.config 中
<system.web>
....
....
<httpHandlers>
....
<add verb="*" path="RESTService/*"
type="PoC.Web.Services.ReSTServiceHandler, PoC.Web.ReSTService"/>
<add verb="*" path="RESTService/*/*"
type="PoC.Web.Services.ReSTServiceHandler, PoC.Web.ReSTService"/>
</httpHandlers>
</system.web>
该库为 ReST Web 服务提供了两种机制
IReSTService
IReSTFulService
与 Web 服务模型相同。 注释需要公开的类的所有方法。
提供四个调用来处理请求:Get、Put、Post 和 Delete。
基于 IReSTService 的 Web 服务
下面显示了 IReSTService
的一个例子
public class Calculator : PoC.Web.Services.IReSTService
{
[PoC.Web.Services.ReSTMethod(PoC.Web.Services.HttpVerb.Get)]
public int Sum(int a, int b)
{
return a + b;
}
[PoC.Web.Services.ReSTMethod(PoC.Web.Services.HttpVerb.Get)]
public int Multiply(int a, int b)
{
return a * b;
}
[PoC.Web.Services.ReSTMethod(PoC.Web.Services.HttpVerb.Get)]
public int Subtract(int a, int b)
{
return a - b;
}
}
在这个例子中,我们有一个 Calculator
类,它实现了 IReSTService
,并通过使用 ReSTMethod
属性注释它们来公开三种方法。 ReSTMethod
属性需要该方法上允许的动词。 就是这样。 如果构建,现在可以通过这些 URL 访问 CalculatorService
- Sum URL: http://<服务器名/localhost>/<web app>/RESTService/Calculator/Sum?a=-1&b=2
- Multiply URL: http:/<服务器名/localhost>/<web app>/RESTService/Calculator/Multiply?a=195&b=21
- Subtract URL: http:/<服务器名/localhost>/<web app>/RESTService/Calculator/Subtract?a=-12&b=2
这是另一个例子
public class ShowNTell : PoC.Web.Services.IReSTService
{
XmlDocument dom = new XmlDocument();
public ShowNTell()
{
dom.LoadXml("<Root><Child><SubChild>" +
"<Parameter></Parameter><MagicNumber>" +
System.Guid.NewGuid().ToString("N") +
"</MagicNumber></SubChild>" +
"</Child></Root>");
}
[PoC.Web.Services.ReSTMethod(PoC.Web.Services.HttpVerb.Get)]
[PoC.Web.Services.ReSTXmlResponse]
public Employee[] Object2Xml()
{
Employee e1 = new Employee();
e1.Name = "Aremac Nokin ";
e1.Id = "11201";
e1.Address = "123 Summer Drive";
e1.City = "Brahman";
e1.Zip = "00001";
e1.JoiningDate = DateTime.Today.AddYears(-5).AddMonths(-3).AddDays(-20);
e1.Salary = 100000.00;
Employee e2 = new Employee();
e2.Name = "Reyalp Sinnet";
e2.Id = "11201";
e2.Address = "123 Summer Drive";
e2.City = "Brahman";
e2.Zip = "00001";
e2.JoiningDate =
DateTime.Today.AddYears(-2).AddMonths(-1).AddDays(-40);
e2.Salary = 200000.00;
return new Employee[] { e1, e2 };
}
[PoC.Web.Services.ReSTMethod(PoC.Web.Services.HttpVerb.Get)]
public XmlNode ReturnNode(string some_param)
{
dom.SelectSingleNode("//Root/Child/SubChild/Parameter").InnerText = some_param;
return dom.SelectSingleNode("//Root/Child/SubChild");
}
[PoC.Web.Services.ReSTMethod(PoC.Web.Services.HttpVerb.Get)]
public XmlDocument ReturnDom(XmlDocument param_1, int param2)
{
dom.SelectSingleNode("//Root/Child/SubChild/Parameter").InnerText =
param2.ToString();
if (param_1 != null && param_1.DocumentElement != null)
{
XmlElement elem = dom.CreateElement("NewItem");
elem.InnerXml = param_1.DocumentElement.OuterXml;
dom.SelectSingleNode("//Root/Child").AppendChild(elem);
}
return dom;
}
}
在这个例子中,我们正在公开一个 POCO 数组,一个 XmlNode
和一个 XmlDocument
。 我们还在此示例中看到了一个新属性 ReSTXmlResponse
。 此属性使引擎 (IHttpHandler
) 通过序列化对象返回对象的 XML 表示。 如果该方法的返回类型是 typeof XmlNode
,则引擎将返回节点的 OuterXml
并将内容类型设置为“xml”。 是的,有一个用于 XmlDocument
/XmlNode
来自 string
的特殊类型转换器 ;-)。
基于 IReSTFulService 的 Web 服务
此接口具有以下方法
object GetCall(string args, HttpContext context)
object PutCall(string args, HttpContext context)
object PostCall(string args, HttpContext context)
object DeleteCall(string args, HttpContext context)
示例如下
public class Parts : PoC.Web.Services.IReSTFulService
{
....
....
#region IReSTFulService Members
public object GetCall(string arg, HttpContext context)
{
if (string.IsNullOrEmpty(arg))
{
return allParts; // typeof Parts[]
}
else
{
return filteredParts; //typeof Parts[]
}
}
public object PutCall(string arg, HttpContext context)
{
Part ps = null;
//Get Part
try
{
ps = PoC.Web.Services.Utilities.TypeConversion.
Deserialize<part>(context.Request.InputStream);
}
catch(Exception ex){ //Bad Stream
throw new PoC.Web.Services.InternalErrorException(503, "Bad Stream");
}
return UpdatePart(ps);// let's say string
}
public object PostCall(string arg, HttpContext context)
{
Part ps = null;
//Get Part
try
{
ps = PoC.Web.Services.Utilities.TypeConversion.
Deserialize<part>(context.Request.InputStream);
}
catch (Exception ex)
{ //Bad Stream
throw new PoC.Web.Services.InternalErrorException(503, "Bad Stream");
}
return InsertPart(ps);
}
public object DeleteCall(string arg, HttpContext context)
{
throw new PoC.Web.Services.InternalErrorException(503, "Method Not Supported");
}
#endregion
}
现在可以通过以下链接访问“Parts”服务
- 获取所有 Parts 的链接:
- 按 ID 获取 Part 的链接:
- 更新 Part:
- 创建新的 Part:
- 删除 Part:
URL: http://<服务器名/localhost>/<Web App name>/RESTService/Parts
HTTP 方法:Get
URL: http://<服务器名/localhost>/<Web App name>/RESTService/Parts/1101
HTTP 方法:Get
URL: http://<服务器名/localhost>/<Web App name>/RESTService/Parts
HTTP 方法:Put
发送主体:'<Part><Id>1103</Id><Name>somet part name</Name><Description>something ...</Description></Part>'
URL: http://<服务器名/localhost>/<Web App name>/RESTService/Parts
HTTP 方法:Post
发送主体:'<Part><Id></Id><Name>somet part name</Name><Description>something ...</Description></Part>'
URL: http://<服务器名/localhost>/<Web App name>/RESTService/Parts/1103
HTTP 方法:Delete
发送主体:'<AuthorizationCode></AuthorizationCode>'