[英]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.