65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIconstarIcon

5.00/5 (11投票s)

2009年7月12日

CPOL

2分钟阅读

viewsIcon

127019

downloadIcon

5550

一个用于 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 服务提供了两种机制

  1. IReSTService
  2. 与 Web 服务模型相同。 注释需要公开的类的所有方法。

  3. IReSTFulService
  4. 提供四个调用来处理请求: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

  1. Sum URL: http://<服务器名/localhost>/<web app>/RESTService/Calculator/Sum?a=-1&b=2
  2. Multiply URL: http:/<服务器名/localhost>/<web app>/RESTService/Calculator/Multiply?a=195&b=21
  3. 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”服务

  1. 获取所有 Parts 的链接:
  2. URL: http://<服务器名/localhost>/<Web App name>/RESTService/Parts

    HTTP 方法:Get

  3. 按 ID 获取 Part 的链接:
  4. URL: http://<服务器名/localhost>/<Web App name>/RESTService/Parts/1101

    HTTP 方法:Get

  5. 更新 Part:
  6. URL: http://<服务器名/localhost>/<Web App name>/RESTService/Parts

    HTTP 方法:Put

    发送主体:'<Part><Id>1103</Id><Name>somet part name</Name><Description>something ...</Description></Part>'

  7. 创建新的 Part:
  8. URL: http://<服务器名/localhost>/<Web App name>/RESTService/Parts

    HTTP 方法:Post

    发送主体:'<Part><Id></Id><Name>somet part name</Name><Description>something ...</Description></Part>'

  9. 删除 Part:
  10. URL: http://<服务器名/localhost>/<Web App name>/RESTService/Parts/1103

    HTTP 方法:Delete

    发送主体:'<AuthorizationCode></AuthorizationCode>'

© . All rights reserved.