Web消息主体风格(Message Body Style)
對于Web HTTP編程模型來說,服務契約中作為操作的方法無須應用OperationContractAttribute特性,只需要根據需要應用WebGetAttribute與WebInvokeAttribute特性即可。前者針對GET HTTP方法,或者則針對其他HTTP方法。WebGetAttribute與WebInvokeAttribute的屬性BodyStyle和IsBodyStyleSetExplicitly涉及到“Web消息主體風格”的話題。
1: [AttributeUsage(AttributeTargets.Method)] 2: public sealed class WebGetAttribute : Attribute, IOperationBehavior 3: { 4: //其他成員 5: public WebMessageBodyStyle BodyStyle { get; set; } 6: } 7:? 8: [AttributeUsage(AttributeTargets.Method)] 9: public sealed class WebInvokeAttribute : Attribute, IOperationBehavior 10: { 11: //其他成員 12: public WebMessageBodyStyle BodyStyle { get; set; } 13: }至于消息主體的風格通過具有如下定義的枚舉WebMessageBodyStyle表示。
1: public enum WebMessageBodyStyle 2: { 3: Bare, 4: Wrapped, 5: WrappedRequest, 6: WrappedResponse 7: }我們知道請求消息和回復消息分別是對操作方法輸入參數和返回值(輸出參數和引用參數)的封裝,WebMessageBodyStyle中的Bare表示請求消息和回復消息的主體部分僅僅包含針對輸入參數和返回值(輸出參數和引用參數)序列化后的內容,而Wrapped則會在外面包裝一個基于當前操作的“封套”。枚舉項WrappedRequest和WrappedResponse用于單獨針對請求消息和回復消息的主體進行封裝。
WebGetAttribute與WebInvokeAttribute的屬性BodyStyle的默認值為Bare。如果該屬性被設置成WrappedRequest,則回復消息主體依然采用Bare風格;如果該屬性被設置成WrappedResponse,則請求消息主體依然采用Bare風格。布爾類型的只讀屬性IsBodyStyleSetExplicitly表示是否針對屬性BodyStyle進行了顯示設置。
目錄?
一、Xml+Bare?
二、Xml+Wrapped?
三、JSON+Bare?
四、JSON+Wrapped?
五、Bare請求消息風格對單一輸入的限制?
六、Bare回復消息風格對單一輸出的限制
一、Xml + Bare
我們通過之前演示的實例來看看針對不同的消息格式(XML和JSON),請求消息和回復消息的主體在采用不同風格的情況下具有怎樣的結構?,F在我們對應用在契約接口IEmployees中的Create操作方法上的WebInvokeAttribute進行了如下的修改,即顯式地指定了請求消息和回復消息的格式(XML)和主體風格(Bare)。同時也將返回類型從void編程了Employee,并直接將創建的Employee對象返回。
1: [ServiceContract] 2: public interface IEmployees 3: { 4: //其他成員 5: [WebInvoke(UriTemplate = "/", Method = "POST", 6: RequestFormat = WebMessageFormat.Xml, 7: ResponseFormat = WebMessageFormat.Xml, 8: BodyStyle = WebMessageBodyStyle.Bare)] 9: Employee Create(Employee employee); 10: } 11:? 12: public class EmployeesService : IEmployees 13: { 14: //其他成員 15: public Employee Create(Employee employee) 16: { 17: employees.Add(employee); 18: return employee; 19: } 20: }我們針對如下所示的代碼通過服務調用添加一個姓名為“王五”的員工。
1: using (ChannelFactory<IEmployees> channelFactory = new ChannelFactory<IEmployees>("employeeService")) 2: { 3: IEmployees proxy = channelFactory.CreateChannel(); 4: proxy.Create(new Employee 5: { 6: Id = "003", 7: Name = "王五", 8: Grade = "G9", 9: Department = "行政部" 10: }); 11: }針對如上所示的服務調用,由于消息格式和主體風格分別為Xml和Bare,所以作為請求消息和回復消息的主體僅僅是Employee對象被序列化后生成的XML片斷,具體內容如下所示。
1: 請求消息主體: 2: <Employee xmlns="http://www.artech.com/" 3: xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> 4: <Department>行政部</Department> 5: <Grade>G9</Grade> 6: <Id>003</Id> 7: <Name>王五</Name> 8: </Employee> 9:? 10: 回復消息主體: 11: <Employee xmlns="http://www.artech.com/" 12: xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> 13: <Department>行政部</Department> 14: <Grade>G9</Grade> 15: <Id>003</Id> 16: <Name>王五</Name> 17: </Employee>二、Xml + Wrapped
現在我們對契約接口略加修改,將應用在操作方法Create上的WebInvokeAttribute特性的屬性BodyStyle設置為Wrapped。
1: [ServiceContract] 2: public interface IEmployees 3: { 4: //其他成員 5: [WebInvoke(UriTemplate = "/", Method = "POST", 6: RequestFormat = WebMessageFormat.Xml, 7: ResponseFormat = WebMessageFormat.Xml, 8: BodyStyle = WebMessageBodyStyle.Wrapped)] 9: Employee Create(Employee employee); 10: }針對相同的服務調用,請求消息和回復消息將具有如下所示的主體內容。我們可以看出Employee被序列化后生成的XML在請求消息中作為<Create>元素的子元素;對于回復消息來說,Employee被序列化后生成的XML的根元素名稱為CreateResult,而不是<Employee>,而整個<CreateResult>內嵌于< CreateResponse >元素中。
1: 請求消息主體: 2: <Create xmlns="http://tempuri.org/"> 3: <employee xmlns:a="http://www.artech.com/" 4: xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> 5: <a:Department>行政部</a:Department> 6: <a:Grade>G9</a:Grade> 7: <a:Id>003</a:Id> 8: <a:Name>王五</a:Name> 9: </employee> 10: </Create> 11:? 12: 回復消息主體: 13: <CreateResponse xmlns="http://tempuri.org/"> 14: <CreateResult xmlns:a="http://www.artech.com/" 15: xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> 16: <a:Department>行政部</a:Department> 17: <a:Grade>G9</a:Grade> 18: <a:Id>003</a:Id> 19: <a:Name>王五</a:Name> 20: </CreateResult> 21: </CreateResponse>三、JSON+ Bare
上面我們通過實例演示了消息格式為Xml情況下針對不同風格的消息主體的內容差異,現在我們按照相同的方式來討論當消息格式為JSON的時候,針對不同風格的消息主體在結構上又具有怎樣差異。如下面的代碼片斷所示,我們通過對契約接口的修改將服務操作Create的消息格式和主體風格設置成Json和Bare。
1: [ServiceContract] 2: public interface IEmployees 3: { 4: //其他成員 5: [WebInvoke(UriTemplate = "/", Method = "POST", 6: RequestFormat = WebMessageFormat.Json, 7: ResponseFormat = WebMessageFormat.Json, 8: BodyStyle = WebMessageBodyStyle.Bare)] 9: Employee Create(Employee employee); 10: }同樣針對之前的服務調用,以JSON形式表示的Employee對象將直接作為請求消息和回復消息的主體部分,具體的內容如下所示。(S1004)
1: 請求消息主體: 2: {"Department":"行政部","Grade":"G9","Id":"003","Name":"王五"} 3:? 4: 回復消息主體: 5: {"Department":"行政部","Grade":"G9","Id":"003","Name":"王五"}四、JSON+ Wrapped
我們最后來演示Json消息格式在Wrapped風格下具有怎樣的結構,為此我們只需要將應用在Create操作方法上的WebInvokeAttribute特性的BodyStyle屬性設置為Wrapped。
1: [ServiceContract] 2: public interface IEmployees 3: { 4: //其他成員 5: [WebInvoke(UriTemplate = "/", Method = "POST", 6: RequestFormat = WebMessageFormat.Json, 7: ResponseFormat = WebMessageFormat.Json, 8: BodyStyle = WebMessageBodyStyle.Wrapped)] 9: Employee Create(Employee employee); 10: }如下面的代碼所示,由于請求消息和回復消息采用Wrapped風格,表示Employee的JSON對象最終作為最終JSON對象的“employee”屬性和“CreateResult”屬性。(S1005)
1: 請求消息主體: 2: {"employee":{"Department":"行政部","Grade":"G9","Id":"003","Name":"王五"}} 3:? 4: 回復消息主體: 5: {"CreateResult":{"Department":"行政部","Grade":"G9","Id":"003","Name":"王五"}}五、Bare請求消息風格對單一輸入的要求
對于Bare消息主體風格來說,意味著對象被序列化后生成的XML或者JSON表示直接作為消息的主體,所以只適用于單一對象。具體來說,只有具有唯一輸入參數的操作方法才能將請求消息的主題風格設置為Bare。
1: [ServiceContract(Namespace = "http://www.artech.com/")] 2: public interface ICalculator 3: { 4: [WebInvoke(BodyStyle = WebMessageBodyStyle.Bare)] 5: double Add( double x, double y); 6: }如上所示的是我們熟悉的計算服務的契約接口的定義。消息主體風格為Bare的操作方法Create具有兩個輸入參數(x和y),在對實現了該契約接口進行寄宿的時候就會拋出如下圖所示的InvalidOperationException異常,提示“約定“ICalculator”的操作‘Add’指定要序列化多個請求正文參數,但沒有任何包裝元素。如果沒有包裝元素,至多可序列化一個正文參數。請刪除多余的正文參數,或將 WebGetAttribute/WebInvokeAttribute 的 BodyStyle 屬性設置為 Wrapped”。
六、Bare回復消息風格對單一輸出的要求
由于回復參數是對返回值、引用參數和輸出參數的封裝,所以當操作方法具有引用參數或者輸出參數時不能將回復消息的主體風格設置為Bare。
1: [ServiceContract(Namespace = "http://www.artech.com/")] 2: public interface ICalculator 3: { 4: [WebInvoke(BodyStyle = WebMessageBodyStyle.WrappedRequest)] 5: void Add( double x, double y, out double result); 6: }同樣以計算服務契約為例,現在我們通過如上的方式以輸出參數的形式返回加法運算的結果,并將應用在操作方法上的WebInvokeAttribute特性的BodyStyle屬性設置為WrappedRequest,這意味著請求消息和回復消息分別采用Wrapped和Bare風格。當我們對實現了該契約接口的服務設施寄宿時會拋出下圖所示的InvalidOperationException異常,并提示“約定‘ICalculator’的操作‘Add’至少指定一個響應正文參數不是操作的返回值。當 WebGetAttribute/WebInvokeAttribute 的 BodyStyle 屬性設置為 Bare 時,只允許使用返回值。請刪除多余的響應正文參數或將 BodyStyle 屬性設置為 Wrapped”。
總結
以上是生活随笔為你收集整理的Web消息主体风格(Message Body Style)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 北上广深人口为什么负增长?
- 下一篇: 奶奶在不知情况下损坏了国家电网录过口供对