现有.NETC#网站中RESTAPI的设计实践

现有.NETC#网站中RESTAPI的设计实践,c#,asp.net,xml,rest,post,C#,Asp.net,Xml,Rest,Post,我想让我们的用户登陆web服务器,将XML发布到我们的计算web服务器(处理XML数据)。登陆和计算web服务器仅通过internet连接,因此最好在计算web服务器上安装REST API,以便发布XML数据进行处理 老实说,我们都是软件工程师,但我们的能力在于算法处理,而不是web管道或ASP.NET本身。我环顾四周,看到WCF(Windows通信基金会)被踢了很多次。我担心WCF对于我们的情况可能过于复杂/设计过度 那么,对于我来说,让现有的基于web表单的处理网站接受发布的XML最简单的方

我想让我们的用户登陆web服务器,将XML发布到我们的计算web服务器(处理XML数据)。登陆和计算web服务器仅通过internet连接,因此最好在计算web服务器上安装REST API,以便发布XML数据进行处理

老实说,我们都是软件工程师,但我们的能力在于算法处理,而不是web管道或ASP.NET本身。我环顾四周,看到WCF(Windows通信基金会)被踢了很多次。我担心WCF对于我们的情况可能过于复杂/设计过度

那么,对于我来说,让现有的基于web表单的处理网站接受发布的XML最简单的方法是什么?我想我需要注册一个URI(在web.config中?)作为API接口,在该URI上有一个处理程序并检索XML字符串-我只是不知道实现步骤:(.所以一个玩具示例或一个指向教程的指针就太棒了!)

顺便说一句,一旦我在处理服务器上有了XML字符串,我就成功了

谢谢
Sid

如果您只想要尽可能薄的层,而不想弄乱管道或计算wcf,请创建一个asp.net web项目,然后右键单击并添加项选择一个httphandler,如果它给出从响应中提取xml字符串的命令。items[strings key]。将其作为ashx?key=您的xml字符串的url发布。好的,因此我阅读了一些文档以回答我自己的问题。基本上WCF REST已经发生了很大的变化。早期版本的设置非常复杂,但在最近的版本(.NET 4和WCF REST starter kit)中,配置开销要小得多

为了快速运行WCF REST,我基本上做了3件事

  • 在global.asax.cs中设置服务的路径(我必须手动将其添加/编辑为global.asax和global.asax.cs)
  • 设置“服务合同”(即内部的“doThisMethod”)
  • 设置“数据契约”(即,如果您通过HTTP主体发布任何XML/JSON,则此“映射”/序列化XML/JSON和本机C#对象)
  • 对于非常基本的REST API(即仅HTTP GET),前两个步骤就足够了。请注意,我在复制粘贴过程中删除了一些内容,但您应该了解

    步骤1a

    global.asax

    <%@ Application Codebehind="~/App_Code/Global.asax.cs" Inherits="MyBLL.Global" Language="C#" %>
    
    步骤2a

    如您所见,我将接口(抽象类)和实际实现拆分为两个单独的文件,以实现清晰的分离

    TestInterface.cs

    using System;
    using System.ServiceModel;
    using System.ServiceModel.Activation;
    using System.ServiceModel.Web;
    
    [ServiceContract]
    interface TestInterface
    {
        [OperationContract]
        string TestAsXML(string extra);
    
        [OperationContract]
        string TestAsJSON(string extra);
    }
    
    步骤2b TestService.cs

    using System;
    using System.ServiceModel;
    using System.ServiceModel.Activation;
    using System.ServiceModel.Web;
    
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class TestService : TestInterface
    
        [WebInvoke(UriTemplate = "Test/{username}", Method = "GET", ResponseFormat = WebMessageFormat.Xml)]
        public string TestAsXML(string username)
        {
            WebOperationContext.Current.OutgoingResponse.ContentType = "text/xml";
            return String.Format("Hello {0}!", String.IsNullOrWhiteSpace(username) ? "world" : username);
        }
    
        [WebInvoke(UriTemplate = "Test/{username}?format=json", Method = "GET", ResponseFormat = WebMessageFormat.Json)]
        public string TestAsJSON(string username)
        {
            // NOTE, if we GET this from a browsers, it will most likely have 
            // "Accept: text/html, application/xhtml+xml, */*" in the HTTP header
            // So the framework will return XML instead. Try from Fiddler2 instead or
            // write your own WCF client or from AJAX
            WebOperationContext.Current.OutgoingResponse.ContentType = "application/json";
            return String.Format("Hello {0}!", String.IsNullOrWhiteSpace(username) ? "world" : username);
        }
    
    步骤3

    对于上面的“测试”示例,所有内容都在URI本身之上(由于GET),因此您不需要下面的内容。实际上,一旦您想要使用POST等,您将需要在HTTP正文中发送对象。交换数据时,使用“数据协定”来利用WCF的功能,如下所示

    在这里,我将在HTTP主体中发送一个类,该类中依次包含一个字符串和一个int

    TestInput.cs

    using System;
    using System.Web;
    using System.Runtime.Serialization;
    
    // "" needed to clear out ugly xmlns namespace tags to make it plain old XML (POX)
    // If you want them, ether take it out or specify on your own
    [DataContract(Name = "TestInput", Namespace = "")] 
    public class TestInput
    {
        // NOTE: If Order property is skipped, the data will be serialized 
        // alphabetically per variable names!!
        // This can kill services, so better to be explicit
        [DataMember(Order = 0)] 
        int SomeNumber;
    
        // NOTE: If Name property is used XML will have UserName instead of internalUserName
        [DataMember(Name="UserName", Order = 1)] 
        string internalUserName;       
    }
    

    1) 如果我把XML字符串(它实际上是一个大文件)塞进URL中,它不是会得到而不是POST吗?POST的一个原因是因为它对我来说不是幂等的……2)我想你指的是提取XML字符串的请求对象,而不是响应对象?如果我将XML字符串作为隐藏的表单字段发送,那么看起来我可以将其读取为
    XMLstr=context.Request.form[indexHiddenXMLField]
    但我怀疑这样做是错误的,因为HTTP请求将看起来像
    内容类型:application/x-www-form-urlencoded Content Length:31 HiddenXMLField=
    我认为内容类型应该反映XML(text/XML?),并且主体应该是真正的XML。这是一种预感-我可能是错的,因为我从未设计过真正的RESTful API3)如何消除.ashx扩展以便server.com\API\incoming.ashx=>server.com\API\incoming(或者可能在最后?)。。。。。我不得不把它分成3条评论来适应。很抱歉我严格地说的是最简单的直接方法,没有任何干扰。正确的方法是使用WCF web服务。虽然在我的方法中,要获得状态,只需使用静态资源(文件、数据库或内存中的文本静态资源)并注意线程安全。对于URL,您只需通过IIS管理器UI转到文件夹的属性,并将incoming.ashx设为默认文档
    using System;
    using System.Web;
    using System.Runtime.Serialization;
    
    // "" needed to clear out ugly xmlns namespace tags to make it plain old XML (POX)
    // If you want them, ether take it out or specify on your own
    [DataContract(Name = "TestInput", Namespace = "")] 
    public class TestInput
    {
        // NOTE: If Order property is skipped, the data will be serialized 
        // alphabetically per variable names!!
        // This can kill services, so better to be explicit
        [DataMember(Order = 0)] 
        int SomeNumber;
    
        // NOTE: If Name property is used XML will have UserName instead of internalUserName
        [DataMember(Name="UserName", Order = 1)] 
        string internalUserName;       
    }