简体   繁体   English

WCF,SOAP,纯老式XML

[英]WCF, SOAP, Plain Old XML

I'm very confused by some things in the Web Service world, and I was hoping that someone could explain it to me. 我对Web服务世界中的某些事情感到非常困惑,我希望有人可以向我解释一下。

Here's what I want: I want to HTTPPost an XML document to https://www.whatever.com/myservice (.???). 这就是我想要的:我想通过HTTPPost XML文档到https://www.whatever.com/myservice (。???)。 In that service, I want to get that XML doc, do stuff, then respond back with an XML doc that is ultra simple -- like " <xml....><success>TRUE</success> " 在该服务中,我想获取该XML文档,进行处理,然后使用超简单的XML文档进行响应-例如“ <xml....><success>TRUE</success>

I can't do SOAP or JSON or anything else. 我无法执行SOAP或JSON或其他任何操作。 I MUST conform to what already exists. 我必须遵守已经存在的条件。 There are hundreds of different companies sending us data in exactly the format that I described, and adding a requirement to enclose it all in SOAP simply isn't possible. 有数百家不同的公司以与我描述的格式完全相同的格式向我们发送数据,因此根本不可能添加要求将其全部封装在SOAP中。

When using a WCF Web Service, it appears that the request to me has to be sent like this: 使用WCF Web服务时,似乎必须向我发送请求,如下所示:

 <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><GetData xmlns="http://tempuri.org/"><value>3</value></GetData></s:Body></s:Envelope>

When using a .asmx page, the response is always sent as an XML document with a namespace (http://tempuri, or if I change it, then to whatever I change it to). 当使用.asmx页面时,响应始终以带有名称空间的XML文档发送(http:// tempuri,或者如果我更改它,则发送到我将其更改为的内容)。 This is unneeded and would likely break all the existing code. 这是不必要的,可能会破坏所有现有代码。

When using a generic handler (.ashx), I can definitely control exactly what gets returned back, but I've been told to stay away from .ashx pages because they carry the full ASP.Net session type code and it is much slower. 使用通用处理程序(.ashx)时,我绝对可以精确控制返回的内容,但是有人告诉我不要使用.ashx页面,因为它们带有完整的ASP.Net会话类型代码,而且速度慢得多。

What would I use to solve this issue and have my code be as fast as possible? 我将使用什么来解决此问题并使我的代码尽可能快?

EDIT: In case anyone cares, the 10,000 requests per hour issue is our peak traffic during the year. 编辑:万一有人在乎,每小时10,000个请求是我们一年中的高峰流量。 We handle 50-60k incoming requests per day on average, but during December it can reach up to 10,000 requests per hour. 我们平均每天处理50-60k个传入请求,但在12月期间,每小时最多可以处理10,000个请求。 And we hope to grow, but to do that, I'll add a load balancer and some more machines in Rackspace. 我们希望有所增长,但要做到这一点,我将在Rackspace中添加一个负载平衡器和更多计算机。

Our current provider of this service is overwhelmed during these times and we miss out on a lot of money because of this. 在这段时间里,我们当前的服务提供商不堪重负,因此我们错过了很多钱。 So, my proxy will do one of our most basic checks on the front side (duplicate check against a database updated hourly) and that will weed out 75% of the traffic we have to send to our current provider. 因此,我的代理服务器将在前端进行最基本的检查之一(每小时对数据库进行一次重复检查),这将淘汰必须发送给当前提供商的流量的75%。 The current provider does underwriting of these leads for us, and I will not be replacing that, merely adding a gatekeeper to reduce stress on their servers. 当前的提供商确实为我们承保了这些潜在客户,我不会取代它,只是增加了网守以减轻服务器压力。

Thanks for all of the help. 感谢您的所有帮助。 I've asked a series of web service questions lately on StackOverflow trying to get my head around many of the issues that I'll be facing. 最近,我在StackOverflow上提出了一系列Web服务问题,以使我着手解决我将要面对的许多问题。

What you are talking about is a POX service -- also known as plain old XML. 您正在谈论的是POX服务-也称为普通旧XML。

Whoever told you IHttpHandlers carry the session code is wrong -- they don't unless you explicitly enable session state . 谁告诉你IHttpHandlers携带会话代码是错误的-除非您显式启用会话状态,否则他们不会这样做。 Now, it does have the ASP.NET pipeline overhead, but unless you are using some lunatic fringe lightweight web socket server this doesn't really matter as any form of IIS hosted service will have similar overhead. 现在,它确实具有ASP.NET管道开销,但是除非您使用某些疯狂的轻量级Web套接字服务器,否则这实际上并不重要,因为任何形式的IIS托管服务都将具有类似的开销。 And, if this is a public-facing internet service, IIS does some neat things for you that you might want. 而且,如果这是面向公众的Internet服务,IIS可能会为您做一些您可能想要的整洁的事情。 Things like SSL, request logging and integration with the other stuff operations is using to watch things. 诸如SSL,请求日志记录以及与其他填充操作的集成之类的内容正在用于监视事物。

As for how to get there, since you've got a defined format ASMX and WCF with default (SOAP) behaviors are out by definition. 至于如何到达那里,由于您已经定义了ASMX和WCF,默认情况下具有默认(SOAP)行为。 For flexibility, the actual logic of the service should be implemented separately leaving the external bits responsible for taking requests, translating from xml and sending the response back as properly formatted XML. 为了提高灵活性,应该单独实现服务的实际逻辑,而保留负责接收请求,从xml转换并以正确格式的XML发送回响应的外部位。

This leaves you with a few options: 这为您提供了一些选择:

  • Probably the simplest, especially if this is bolting onto an existing .NET site, would be a custom IHttpHandler. 可能最简单的方法是自定义IHttpHandler,特别是如果将其附加到现有的.NET站点上时。 You'll have to much around a bit lower down the stack than in other places but if this is really taking one set of XML in and spitting a response back the work isn't insurmountable. 与其他地方相比,您将不得不在堆栈上降低很多,但是如果这确实是采用一组XML并将响应随地吐出来的话,那么这并不是无法克服的。 One big advantage is that you have finite control over the output side, so if you've got a long-running task you can can stream responses pretty easily. 一个很大的优点是您可以对输出端进行有限的控制,因此,如果您有一个长期运行的任务,则可以轻松地流式传输响应。

  • ASP.NET MVC web service would perhaps be simpler than a IHttpHandler inasmuch as you won't have to dive into the POST variables so much and would also makes sense if you are bolting onto a MVC site. ASP.NET MVC Web服务可能比IHttpHandler更简单,因为您不必过多地讨论POST变量,并且如果您使用MVC站点也很有意义。

  • WCF with webhttp bindings could work if the XML is formatted in a manner it doesn't mind. 如果XML格式不正确,则带有webhttp绑定的WCF可以工作。 But you will have some stack boogeymen to slay as WCF, in my experience, never wants to exactly fit some sort of XML you like to see on the wire. 但是,根据我的经验,您将需要像WCF一样使用一些堆叠的boogeymen,他们绝对不想完全适合您想在网络上看到的某种XML。

  • Something alternative, such as OpenRasta , could work very well here. 诸如OpenRasta之类的替代方法在这里可以很好地工作。 It is really meant for these sorts of POX style scenarios and will very easily let you use your xml formats, etc. 它确实适用于这类POX样式方案,并且非常容易让您使用xml格式等。

Insofar as speed, the real question to answer is not "is this the fastest it could be" but rather "is this fast enough?" 就速度而言,真正要回答的问题不是“这可能是最快的吗”,而是“这足够快吗?” Especially considering the nature of HTTP and remote communications means that, in most cases, any server-side efficiencies you might be able to create don't really matter because it takes hundreds of times longer for the request to transit across the wire than for it to get processed. 特别是考虑到HTTP和远程通信的本质,这意味着在大多数情况下,您可能能够创建的任何服务器端效率都无关紧要,因为请求在网络上传输的时间比在网络上传输的时间长数百倍。得到处理。 If you do have a relatively clean implementation of the service logic, then you'll be in good position to switch communications stacks until you find the one that works the best for you. 如果确实有一个相对干净的服务逻辑实现,那么您将处于切换通信堆栈的有利位置,直到找到最适合您的通信堆栈。

It little depends on what kind of application do you have? 这几乎取决于您拥有哪种应用程序? If it is ASP.net WebForms, you might just have standard Page, with Page_Load method in which you can handle request and put anything you like in HttpCurrent.HttpContex.Response object. 如果是ASP.net WebForms,则可能只有标准的Page,带有Page_Load方法,您可以在其中处理请求并将喜欢的任何内容放入HttpCurrent.HttpContex.Response对象。

If it is MVC, you should have an action with custom ActionResult. 如果是MVC,则应使用自定义ActionResult进行操作。

But as for me I don't see anything wrong with Generic Handlers .ashx. 但是对于我来说,通用处理程序.ashx没有任何问题。 I would go with it. 我会同意的。

Try a "bare" repsonse: http://msdn.microsoft.com/en-us/library/system.servicemodel.web.webmessagebodystyle.aspx 尝试“裸露”答复: http : //msdn.microsoft.com/zh-cn/library/system.servicemodel.web.webmessagebodystyle.aspx

[OperationContract]
[WebInvoke(BodyStyle = WebMessageBodyStyle.Bare)]

Or perhaps in your case, if your request is wrapped but you want a simple unwrapped response: 或者,在您的情况下,如果您的请求已包装但您想要一个简单的未包装响应:

[OperationContract]
[WebInvoke(BodyStyle = WebMessageBodyStyle.WrappedRequest)]

I usually use WrappedRequest 我通常使用WrappedRequest

Ashx as generic handler doesn't have session until you specify it . ASHX作为一般的处理程序,直到你没有会话指定它 What you describe is sometimes called XML service. 您描述的内容有时称为XML服务。 WCF by default allows SOAP and REST services. WCF默认情况下允许SOAP和REST服务。 I'm not sure if you can use unique URL per resource (message type) which would allow you using REST service. 我不确定是否可以为每个资源(消息类型)使用唯一的URL,这将允许您使用REST服务。 It means your url would look like https://www.whatever.com/myservice/something where something would be used to map to operation marked with WebInvoke attribute as: 这意味着您的网址看起来像https://www.whatever.com/myservice/something ,其中某些内容将用于映射到标有WebInvoke属性的操作:

[ServiceContract]
public interface IService
{
    [OperationContract]
    [WebInvoke(Method = "POST", UriTemplate="Something", 
               BodyStyle = WebMessageBodyStyle.Bare, 
               RequestFormat = WebMessageFormat.Xml,
               ResponseFormat = WebMessageFormat.Xml)]
    CompositeTypeMessage GetData(CompositeTypeMessage composite);
}

You can also use native WCF without REST to define XML service but it requires a lot of effort: 您也可以使用不带REST的本机WCF来定义XML服务,但这需要很多工作:

First you have to define custom binding where the important part is messageVersion=None . 首先,您必须定义自定义绑定,其中重要的部分是messageVersion=None

<bindings>
  <customBinding>
    <binding name="XmlService">
      <textMessageEncoding messageVersion="None"/>
      <httpTransport/>
    </binding>
  </customBinding>
</bindings>
<services>
  <service name="XmlService.Service">
    <endpoint address="" binding="customBinding" bindingConfiguration="XmlService" contract="XmlService.IService"/>
    <host>
      <baseAddresses>
        <add baseAddress="http://localhost:8732/XmlService"/>
      </baseAddresses>
    </host>
  </service>
</services>

Then you have to define contracts and remove default namespace: 然后,您必须定义合同并删除默认名称空间:

[ServiceContract(Namespace = "")]
public interface IService
{
    [OperationContract]
    CompositeTypeMessage GetData(CompositeTypeMessage composite);
}

// Now here you can make main decission. Do you want wrapper for data
// or not. If you don't use message contract and use data contract directly
// each request will be wrapped in the element with the same name as operation
// and response will be wrapped in the element with the name of operation + 
// Response suffix. Message contract allows you defining custom wrapper name
// or turning it off.
[MessageContract (WrapperNamespace = "", IsWrapped = false)]
public class CompositeTypeMessage
{
    [MessageBodyMember(Namespace = "")]
    public CompositeType Data { get; set; }
}

[DataContract(Namespace = "")]
public class CompositeType
{
    bool boolValue = true;
    string stringValue = "Hello ";

    [DataMember]
    public bool BoolValue
    {
        get { return boolValue; }
        set { boolValue = value; }
    }

    [DataMember]
    public string StringValue
    {
        get { return stringValue; }
        set { stringValue = value; }
    }
}

The last point is implementing custom IDispatchOperationSelector behavior. 最后一点是实现自定义IDispatchOperationSelector行为。 Removing all SOAP related features breaks current WCF ability to select correct operation to process a message. 删除所有与SOAP相关的功能会破坏当前的WCF选择正确操作以处理消息的WCF功能。 You must define a new one which will for example select operation by some convention based on root request element. 您必须定义一个新的对象,例如,它将基于根请求元素以某种约定选择操作。 Here is MSDN sample how to build and use similar behavior. 是MSDN示例如何构建和使用类似行为。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM