[英]WCF, SOAP, Plain Old XML
我对Web服务世界中的某些事情感到非常困惑,我希望有人可以向我解释一下。
这就是我想要的:我想通过HTTPPost XML文档到https://www.whatever.com/myservice (。???)。 在该服务中,我想获取该XML文档,进行处理,然后使用超简单的XML文档进行响应-例如“ <xml....><success>TRUE</success>
”
我无法执行SOAP或JSON或其他任何操作。 我必须遵守已经存在的条件。 有数百家不同的公司以与我描述的格式完全相同的格式向我们发送数据,因此根本不可能添加要求将其全部封装在SOAP中。
使用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>
当使用.asmx页面时,响应始终以带有名称空间的XML文档发送(http:// tempuri,或者如果我更改它,则发送到我将其更改为的内容)。 这是不必要的,可能会破坏所有现有代码。
使用通用处理程序(.ashx)时,我绝对可以精确控制返回的内容,但是有人告诉我不要使用.ashx页面,因为它们带有完整的ASP.Net会话类型代码,而且速度慢得多。
我将使用什么来解决此问题并使我的代码尽可能快?
编辑:万一有人在乎,每小时10,000个请求是我们一年中的高峰流量。 我们平均每天处理50-60k个传入请求,但在12月期间,每小时最多可以处理10,000个请求。 我们希望有所增长,但要做到这一点,我将在Rackspace中添加一个负载平衡器和更多计算机。
在这段时间里,我们当前的服务提供商不堪重负,因此我们错过了很多钱。 因此,我的代理服务器将在前端进行最基本的检查之一(每小时对数据库进行一次重复检查),这将淘汰必须发送给当前提供商的流量的75%。 当前的提供商确实为我们承保了这些潜在客户,我不会取代它,只是增加了网守以减轻服务器压力。
感谢您的所有帮助。 最近,我在StackOverflow上提出了一系列Web服务问题,以使我着手解决我将要面对的许多问题。
您正在谈论的是POX服务-也称为普通旧XML。
谁告诉你IHttpHandlers携带会话代码是错误的-除非您显式启用会话状态,否则他们不会这样做。 现在,它确实具有ASP.NET管道开销,但是除非您使用某些疯狂的轻量级Web套接字服务器,否则这实际上并不重要,因为任何形式的IIS托管服务都将具有类似的开销。 而且,如果这是面向公众的Internet服务,IIS可能会为您做一些您可能想要的整洁的事情。 诸如SSL,请求日志记录以及与其他填充操作的集成之类的内容正在用于监视事物。
至于如何到达那里,由于您已经定义了ASMX和WCF,默认情况下具有默认(SOAP)行为。 为了提高灵活性,应该单独实现服务的实际逻辑,而保留负责接收请求,从xml转换并以正确格式的XML发送回响应的外部位。
这为您提供了一些选择:
可能最简单的方法是自定义IHttpHandler,特别是如果将其附加到现有的.NET站点上时。 与其他地方相比,您将不得不在堆栈上降低很多,但是如果这确实是采用一组XML并将响应随地吐出来的话,那么这并不是无法克服的。 一个很大的优点是您可以对输出端进行有限的控制,因此,如果您有一个长期运行的任务,则可以轻松地流式传输响应。
ASP.NET MVC Web服务可能比IHttpHandler更简单,因为您不必过多地讨论POST变量,并且如果您使用MVC站点也很有意义。
如果XML格式不正确,则带有webhttp绑定的WCF可以工作。 但是,根据我的经验,您将需要像WCF一样使用一些堆叠的boogeymen,他们绝对不想完全适合您想在网络上看到的某种XML。
诸如OpenRasta之类的替代方法在这里可以很好地工作。 它确实适用于这类POX样式方案,并且非常容易让您使用xml格式等。
就速度而言,真正要回答的问题不是“这可能是最快的吗”,而是“这足够快吗?” 特别是考虑到HTTP和远程通信的本质,这意味着在大多数情况下,您可能能够创建的任何服务器端效率都无关紧要,因为请求在网络上传输的时间比在网络上传输的时间长数百倍。得到处理。 如果确实有一个相对干净的服务逻辑实现,那么您将处于切换通信堆栈的有利位置,直到找到最适合您的通信堆栈。
这几乎取决于您拥有哪种应用程序? 如果是ASP.net WebForms,则可能只有标准的Page,带有Page_Load方法,您可以在其中处理请求并将喜欢的任何内容放入HttpCurrent.HttpContex.Response对象。
如果是MVC,则应使用自定义ActionResult进行操作。
但是对于我来说,通用处理程序.ashx没有任何问题。 我会同意的。
尝试“裸露”答复: http : //msdn.microsoft.com/zh-cn/library/system.servicemodel.web.webmessagebodystyle.aspx
[OperationContract]
[WebInvoke(BodyStyle = WebMessageBodyStyle.Bare)]
或者,在您的情况下,如果您的请求已包装但您想要一个简单的未包装响应:
[OperationContract]
[WebInvoke(BodyStyle = WebMessageBodyStyle.WrappedRequest)]
我通常使用WrappedRequest
ASHX作为一般的处理程序,直到你没有会话指定它 。 您描述的内容有时称为XML服务。 WCF默认情况下允许SOAP和REST服务。 我不确定是否可以为每个资源(消息类型)使用唯一的URL,这将允许您使用REST服务。 这意味着您的网址看起来像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);
}
您也可以使用不带REST的本机WCF来定义XML服务,但这需要很多工作:
首先,您必须定义自定义绑定,其中重要的部分是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>
然后,您必须定义合同并删除默认名称空间:
[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; }
}
}
最后一点是实现自定义IDispatchOperationSelector
行为。 删除所有与SOAP相关的功能会破坏当前的WCF选择正确操作以处理消息的WCF功能。 您必须定义一个新的对象,例如,它将基于根请求元素以某种约定选择操作。 这是MSDN示例如何构建和使用类似行为。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.