ContractDescriptionTest.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606
  1. //
  2. // ContractDescriptionTest.cs
  3. //
  4. // Author:
  5. // Atsushi Enomoto <[email protected]>
  6. //
  7. // Copyright (C) 2005 Novell, Inc. http://www.novell.com
  8. //
  9. // Permission is hereby granted, free of charge, to any person obtaining
  10. // a copy of this software and associated documentation files (the
  11. // "Software"), to deal in the Software without restriction, including
  12. // without limitation the rights to use, copy, modify, merge, publish,
  13. // distribute, sublicense, and/or sell copies of the Software, and to
  14. // permit persons to whom the Software is furnished to do so, subject to
  15. // the following conditions:
  16. //
  17. // The above copyright notice and this permission notice shall be
  18. // included in all copies or substantial portions of the Software.
  19. //
  20. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  21. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  22. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  23. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  24. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  25. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  26. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  27. //
  28. using System;
  29. using System.Collections.ObjectModel;
  30. using System.Net.Security;
  31. using System.Reflection;
  32. using System.ServiceModel;
  33. using System.ServiceModel.Channels;
  34. using System.ServiceModel.Description;
  35. using NUnit.Framework;
  36. namespace MonoTests.System.ServiceModel
  37. {
  38. [TestFixture]
  39. public class ContractDescriptionTest
  40. {
  41. [Test]
  42. [ExpectedException (typeof (InvalidOperationException))]
  43. public void GetNonContract ()
  44. {
  45. ContractDescription cd = ContractDescription.GetContract (
  46. typeof (object));
  47. }
  48. [Test]
  49. public void GetContract ()
  50. {
  51. InternalTestGetContract (
  52. ContractDescription.GetContract (typeof (IFoo)));
  53. }
  54. [Test]
  55. public void GetContractParamRenamed ()
  56. {
  57. ContractDescription cd = ContractDescription.GetContract (typeof (IFooMsgParams));
  58. Assert.AreEqual (1, cd.Operations.Count, "Operation count");
  59. // Operation #1
  60. OperationDescription od = cd.Operations [0];
  61. ServiceAssert.AssertOperationDescription (
  62. "MyFoo", null, null,
  63. typeof (IFooMsgParams).GetMethod ("Foo"),
  64. true, false, false,
  65. od, "MyFoo");
  66. // Operation #1 -> Message #1
  67. MessageDescription md = od.Messages [0];
  68. ServiceAssert.AssertMessageAndBodyDescription (
  69. "http://tempuri.org/IFooMsgParams/MyFoo",
  70. MessageDirection.Input,
  71. null, "MyFoo", "http://tempuri.org/", false,
  72. md, "MyFoo");
  73. ServiceAssert.AssertMessagePartDescription (
  74. "MyParam", "http://tempuri.org/", 0, false,
  75. ProtectionLevel.None, typeof (string), md.Body.Parts [0], "MyFoo.msg");
  76. md = od.Messages [1];
  77. ServiceAssert.AssertMessageAndBodyDescription (
  78. "http://tempuri.org/IFooMsgParams/MyFooResponse",
  79. MessageDirection.Output,
  80. null, "MyFooResponse",
  81. "http://tempuri.org/", true,
  82. md, "MyFoo");
  83. ServiceAssert.AssertMessagePartDescription (
  84. "MyResult", "http://tempuri.org/", 0, false,
  85. ProtectionLevel.None, typeof (string), md.Body.ReturnValue, "MyResult ReturnValue");
  86. }
  87. [Test]
  88. public void GetContractConfigName ()
  89. {
  90. ContractDescription cd = ContractDescription.GetContract (typeof (ICtorUseCase2));
  91. Assert.AreEqual("CtorUseCase2", cd.ConfigurationName);
  92. Assert.AreEqual("ICtorUseCase2", cd.Name);
  93. cd = ContractDescription.GetContract (typeof (ICtorUseCase1));
  94. Assert.AreEqual("MonoTests.System.ServiceModel.ICtorUseCase1", cd.ConfigurationName);
  95. Assert.AreEqual("ICtorUseCase1", cd.Name);
  96. }
  97. [Test]
  98. public void GetContract2 ()
  99. {
  100. InternalTestGetContract (
  101. ContractDescription.GetContract (typeof (Foo)));
  102. }
  103. public void InternalTestGetContract (ContractDescription cd)
  104. {
  105. ServiceAssert.AssertContractDescription (
  106. "IFoo", "http://tempuri.org/", SessionMode.Allowed, typeof (IFoo), null,
  107. cd, "contract");
  108. Assert.AreEqual (2, cd.Operations.Count, "Operation count");
  109. // Operation #1
  110. OperationDescription od = cd.Operations [0];
  111. ServiceAssert.AssertOperationDescription (
  112. "HeyDude", null, null,
  113. typeof (IFoo).GetMethod ("HeyDude"),
  114. true, false, false,
  115. od, "HeyDude");
  116. // Operation #1 -> Message #1
  117. MessageDescription md = od.Messages [0];
  118. ServiceAssert.AssertMessageAndBodyDescription (
  119. "http://tempuri.org/IFoo/HeyDude",
  120. MessageDirection.Input,
  121. null, "HeyDude", "http://tempuri.org/", false,
  122. md, "HeyDude");
  123. ServiceAssert.AssertMessagePartDescription (
  124. "msg", "http://tempuri.org/", 0, false,
  125. ProtectionLevel.None, typeof (string), md.Body.Parts [0], "HeyDude.msg");
  126. ServiceAssert.AssertMessagePartDescription (
  127. "msg2", "http://tempuri.org/", 1, false,
  128. ProtectionLevel.None, typeof (string), md.Body.Parts [1], "HeyDude.msg");
  129. // Operation #1 -> Message #2
  130. md = od.Messages [1];
  131. ServiceAssert.AssertMessageAndBodyDescription (
  132. "http://tempuri.org/IFoo/HeyDudeResponse",
  133. MessageDirection.Output,
  134. null, "HeyDudeResponse",
  135. "http://tempuri.org/", true,
  136. md, "HeyDude");
  137. ServiceAssert.AssertMessagePartDescription (
  138. "HeyDudeResult", "http://tempuri.org/", 0, false,
  139. ProtectionLevel.None, typeof (string), md.Body.ReturnValue, "HeyDudeResponse ReturnValue");
  140. // Operation #2
  141. od = cd.Operations [1];
  142. ServiceAssert.AssertOperationDescription (
  143. "HeyHey", null, null,
  144. typeof (IFoo).GetMethod ("HeyHey"),
  145. true, false, false,
  146. od, "HeyHey");
  147. // Operation #2 -> Message #1
  148. md = od.Messages [0];
  149. ServiceAssert.AssertMessageAndBodyDescription (
  150. "http://tempuri.org/IFoo/HeyHey",
  151. MessageDirection.Input,
  152. null, "HeyHey", "http://tempuri.org/", false,
  153. md, "HeyHey");
  154. ServiceAssert.AssertMessagePartDescription (
  155. "ref1", "http://tempuri.org/", 0, false,
  156. ProtectionLevel.None, typeof (string), md.Body.Parts [0], "HeyHey.ref1");
  157. // Operation #2 -> Message #2
  158. md = od.Messages [1];
  159. ServiceAssert.AssertMessageAndBodyDescription (
  160. "http://tempuri.org/IFoo/HeyHeyResponse",
  161. MessageDirection.Output,
  162. null, "HeyHeyResponse",
  163. "http://tempuri.org/", true,
  164. md, "HeyHey");
  165. ServiceAssert.AssertMessagePartDescription (
  166. "HeyHeyResult", "http://tempuri.org/", 0, false,
  167. ProtectionLevel.None, typeof (void), md.Body.ReturnValue, "HeyHeyResponse ReturnValue");
  168. ServiceAssert.AssertMessagePartDescription (
  169. "out1", "http://tempuri.org/", 0, false,
  170. ProtectionLevel.None, typeof (string), md.Body.Parts [0], "HeyHey.out1");
  171. ServiceAssert.AssertMessagePartDescription (
  172. "ref1", "http://tempuri.org/", 1, false,
  173. ProtectionLevel.None, typeof (string), md.Body.Parts [1], "HeyHey.ref1");
  174. }
  175. [Test]
  176. public void GetContractInherit ()
  177. {
  178. ContractDescription.GetContract (typeof (Foo));
  179. }
  180. [Test]
  181. [ExpectedException (typeof (InvalidOperationException))]
  182. public void GetMultipleServiceContract ()
  183. {
  184. ContractDescription.GetContract (typeof (FooBar));
  185. }
  186. [Test]
  187. // [ExpectedException (typeof (InvalidOperationException))]
  188. public void GetContractNoOperation ()
  189. {
  190. ContractDescription.GetContract (typeof (INoOperation));
  191. }
  192. [Test]
  193. [Category ("NotWorking")]
  194. public void GetContractMessageParameter ()
  195. {
  196. ContractDescription cd = ContractDescription.GetContract (typeof (IMessageParameter));
  197. ServiceAssert.AssertContractDescription (
  198. "IMessageParameter", "http://tempuri.org/",
  199. SessionMode.Allowed, typeof (IMessageParameter), null,
  200. cd, "contract");
  201. OperationDescription od = cd.Operations [0];
  202. ServiceAssert.AssertOperationDescription (
  203. "ReturnMessage", null, null,
  204. typeof (IMessageParameter).GetMethod ("ReturnMessage"),
  205. true, false, false,
  206. od, "operation");
  207. MessageDescription md = od.Messages [0];
  208. ServiceAssert.AssertMessageAndBodyDescription (
  209. "http://tempuri.org/IMessageParameter/ReturnMessage",
  210. MessageDirection.Input,
  211. // Body.WrapperName is null
  212. null, null, null, false,
  213. md, "ReturnMessage");
  214. ServiceAssert.AssertMessagePartDescription (
  215. "arg", "http://tempuri.org/", 0, false,
  216. ProtectionLevel.None, typeof (Message), md.Body.Parts [0], "ReturnMessage input");
  217. }
  218. [Test]
  219. [ExpectedException (typeof (InvalidOperationException))]
  220. public void GetContractInvalidAsync ()
  221. {
  222. ContractDescription.GetContract (typeof (IInvalidAsync));
  223. }
  224. [Test]
  225. // IMetadataExchange contains async patterns.
  226. public void GetContractIMetadataExchange ()
  227. {
  228. ContractDescription cd = ContractDescription.GetContract (typeof (IMetadataExchange));
  229. OperationDescription od = cd.Operations [0];
  230. Assert.AreEqual (2, od.Messages.Count, "premise: message count");
  231. foreach (MessageDescription md in od.Messages) {
  232. if (md.Direction == MessageDirection.Input) {
  233. Assert.AreEqual ("http://schemas.xmlsoap.org/ws/2004/09/transfer/Get", md.Action, "#1-1");
  234. Assert.AreEqual (1, md.Body.Parts.Count, "#1-2");
  235. Assert.IsNull (md.Body.ReturnValue, "#1-3");
  236. Assert.AreEqual (typeof (Message), md.Body.Parts [0].Type, "#1-4");
  237. } else {
  238. Assert.AreEqual ("http://schemas.xmlsoap.org/ws/2004/09/transfer/GetResponse", md.Action, "#2-1");
  239. Assert.AreEqual (0, md.Body.Parts.Count, "#2-2");
  240. Assert.IsNotNull (md.Body.ReturnValue, "#2-3");
  241. Assert.AreEqual (typeof (Message), md.Body.ReturnValue.Type, "#2-4");
  242. }
  243. }
  244. }
  245. [Test]
  246. // enable it if we want to become a compatibility kid. It has
  247. // no ServiceContract, thus it should not be accepted. But
  248. // there is an abuse of ChannelFactory<IRequestChannel> in
  249. // MSDN documentations and probably examples.
  250. [Category ("NotWorking")]
  251. public void GetContractIRequestChannel ()
  252. {
  253. ContractDescription cd = ContractDescription.GetContract (typeof (IRequestChannel));
  254. Assert.AreEqual (typeof (IRequestChannel), cd.ContractType, "#_1");
  255. Assert.AreEqual ("IRequestChannel", cd.Name, "#_2");
  256. Assert.AreEqual ("http://schemas.microsoft.com/2005/07/ServiceModel", cd.Namespace, "#_3");
  257. Assert.AreEqual (false, cd.HasProtectionLevel, "#_4");
  258. Assert.AreEqual (SessionMode.NotAllowed, cd.SessionMode, "#_5");
  259. Assert.AreEqual (0, cd.Behaviors.Count, "#_6");
  260. Assert.AreEqual (1, cd.Operations.Count, "#_7");
  261. OperationDescription od = cd.Operations [0];
  262. Assert.IsNull (od.SyncMethod, "#_8");
  263. Assert.IsNull (od.BeginMethod, "#_9");
  264. Assert.IsNull (od.EndMethod, "#_10");
  265. Assert.AreEqual (false, od.IsOneWay, "#_11");
  266. Assert.AreEqual (false, od.HasProtectionLevel, "#_12");
  267. Assert.AreEqual ("Request", od.Name, "#_13");
  268. Assert.AreEqual (true, od.IsInitiating, "#_14");
  269. Assert.AreEqual (0, od.Behaviors.Count, "#_15");
  270. Assert.AreEqual (2, od.Messages.Count, "#_16");
  271. foreach (MessageDescription md in od.Messages) {
  272. if (md.Direction == MessageDirection.Output) {
  273. Assert.AreEqual ("*", md.Action, "#_17");
  274. Assert.AreEqual (false, md.HasProtectionLevel, "#_18");
  275. Assert.AreEqual (0, md.Headers.Count, "#_19");
  276. Assert.AreEqual (0, md.Properties.Count, "#_20");
  277. Assert.IsNull (md.MessageType, "#_21");
  278. MessageBodyDescription mb = md.Body;
  279. Assert.AreEqual (null, mb.WrapperName, "#_22");
  280. Assert.AreEqual (null, mb.WrapperNamespace, "#_23");
  281. Assert.IsNull (mb.ReturnValue, "#_24");
  282. Assert.AreEqual (0, mb.Parts.Count, "#_25");
  283. } else {
  284. Assert.AreEqual ("*", md.Action, "#_17_");
  285. Assert.AreEqual (false, md.HasProtectionLevel, "#_18_");
  286. Assert.AreEqual (0, md.Headers.Count, "#_19_");
  287. Assert.AreEqual (0, md.Properties.Count, "#_20_");
  288. Assert.IsNull (md.MessageType, "#_21_");
  289. MessageBodyDescription mb = md.Body;
  290. Assert.AreEqual (null, mb.WrapperName, "#_22_");
  291. Assert.AreEqual (null, mb.WrapperNamespace, "#_23_");
  292. Assert.IsNull (mb.ReturnValue, "#_24_");
  293. Assert.AreEqual (0, mb.Parts.Count, "#_25_");
  294. }
  295. }
  296. }
  297. [Test]
  298. [ExpectedException (typeof (InvalidOperationException))]
  299. public void WrongAsyncEndContract ()
  300. {
  301. ContractDescription.GetContract (typeof (IWrongAsyncEndContract));
  302. }
  303. [Test]
  304. public void AsyncContract1 ()
  305. {
  306. ContractDescription cd =
  307. ContractDescription.GetContract (typeof (IAsyncContract1));
  308. Assert.AreEqual (1, cd.Operations.Count);
  309. OperationDescription od = cd.Operations [0];
  310. Assert.AreEqual ("Sum", od.Name, "#1");
  311. Assert.IsNotNull (od.BeginMethod, "#2");
  312. Assert.IsNotNull (od.EndMethod, "#3");
  313. }
  314. [Test]
  315. [ExpectedException (typeof (InvalidOperationException))]
  316. public void DuplicateOperationNames ()
  317. {
  318. ContractDescription.GetContract (typeof (IDuplicateOperationNames));
  319. }
  320. [Test]
  321. [ExpectedException (typeof (InvalidOperationException))]
  322. public void AsyncMethodNameDoesNotStartWithBegin ()
  323. {
  324. ContractDescription.GetContract (typeof (IAsyncMethodNameDoesNotStartWithBegin));
  325. }
  326. [Test]
  327. [ExpectedException (typeof (InvalidOperationException))]
  328. public void AsyncNameDoesNotStartWithBeginButExplicitName ()
  329. {
  330. // it is still invalid ...
  331. ContractDescription.GetContract (typeof (IAsyncNameDoesNotStartWithBeginButExplicitName));
  332. }
  333. [Test]
  334. public void MessageBodyMemberIsNotInferred ()
  335. {
  336. ContractDescription cd = ContractDescription.GetContract (typeof (MessageBodyMemberIsNotInferredService));
  337. OperationDescription od = cd.Operations [0];
  338. MessageDescription md = od.Messages [0];
  339. Assert.AreEqual (0, md.Body.Parts.Count);
  340. }
  341. [Test]
  342. public void TestContractFromObject () {
  343. ContractDescription cd = ContractDescription.GetContract (typeof (Foo));
  344. ServiceAssert.AssertContractDescription (typeof (IFoo).Name, "http://tempuri.org/", SessionMode.Allowed, typeof (IFoo), null, cd, "#1");
  345. Assert.AreEqual (cd.Operations.Count, 2);
  346. OperationBehaviorAttribute op = cd.Operations.Find ("HeyHey").Behaviors.Find<OperationBehaviorAttribute> ();
  347. Assert.IsNotNull (op);
  348. Assert.AreEqual (
  349. op.ReleaseInstanceMode,
  350. ReleaseInstanceMode.None, "#2");
  351. cd = ContractDescription.GetContract (typeof (IFoo), typeof (Foo));
  352. ServiceAssert.AssertContractDescription (typeof (IFoo).Name, "http://tempuri.org/", SessionMode.Allowed, typeof (IFoo), null, cd, "#3");
  353. Assert.AreEqual (cd.Operations.Count, 2, "#4");
  354. Assert.AreEqual (
  355. cd.Operations.Find ("HeyHey").Behaviors.Find<OperationBehaviorAttribute> ().ReleaseInstanceMode,
  356. ReleaseInstanceMode.AfterCall, "#5");
  357. }
  358. // It is for testing attribute search in interfaces.
  359. public class Foo : IFoo
  360. {
  361. public string HeyDude (string msg, string msg2)
  362. {
  363. return null;
  364. }
  365. [OperationBehavior (ReleaseInstanceMode = ReleaseInstanceMode.AfterCall)]
  366. public void HeyHey (out string out1, ref string ref1)
  367. {
  368. out1 = null;
  369. }
  370. }
  371. // It inherits both IFoo and IBar, thus cannot be a contract.
  372. public class FooBar : IFoo, IBar
  373. {
  374. public string HeyDude (string msg, string msg2)
  375. {
  376. return null;
  377. }
  378. public void HeyHey (out string out1, ref string ref1)
  379. {
  380. out1 = null;
  381. }
  382. public void OpenBar () {}
  383. }
  384. [ServiceContract]
  385. public interface IFoo
  386. {
  387. [OperationContract]
  388. string HeyDude (string msg, string msg2);
  389. [OperationContract]
  390. void HeyHey (out string out1, ref string ref1);
  391. }
  392. [ServiceContract]
  393. public interface IFoo2
  394. {
  395. // FIXME: it does not pass yet
  396. [OperationContract]
  397. OregoMessage Nanoda (OregoMessage msg);
  398. // FIXME: it does not pass yet
  399. [OperationContract]
  400. OregoMessage Nanoda2 (OregoMessage msg1, OregoMessage msg2);
  401. // FIXME: it does not pass yet
  402. [OperationContract]
  403. Mona NewMona (Mona source);
  404. }
  405. [ServiceContract]
  406. public interface IBar
  407. {
  408. [OperationContract]
  409. void OpenBar ();
  410. }
  411. [MessageContract]
  412. public class OregoMessage
  413. {
  414. [MessageBodyMember]
  415. public string Neutral;
  416. [MessageBodyMember]
  417. public Assembly Huh;
  418. [MessageBodyMember] // it should be ignored ...
  419. public string Setter { set { } }
  420. public string NonMember;
  421. }
  422. public class Mona
  423. {
  424. public string OmaeMona;
  425. public string OreMona;
  426. }
  427. [ServiceContract]
  428. public interface INoOperation
  429. {
  430. }
  431. [ServiceContract]
  432. public interface IMessageParameter
  433. {
  434. [OperationContract]
  435. Message ReturnMessage (Message arg);
  436. }
  437. [ServiceContract]
  438. public interface IInvalidAsync
  439. {
  440. [OperationContract]
  441. Message ReturnMessage (Message arg);
  442. [OperationContract (AsyncPattern = true)]
  443. IAsyncResult BeginReturnMessage (Message arg, AsyncCallback callback, object state);
  444. // and no EndReturnMessage().
  445. }
  446. [ServiceContract]
  447. public interface IWrongAsyncEndContract
  448. {
  449. [OperationContract]
  450. int Sum (int a, int b);
  451. [OperationContract (AsyncPattern = true)]
  452. IAsyncResult BeginSum (int a, int b, AsyncCallback cb, object state);
  453. // this OperationContractAttribute is not allowed.
  454. [OperationContract (AsyncPattern = true)]
  455. int EndSum (IAsyncResult result);
  456. }
  457. [ServiceContract]
  458. public interface IAsyncContract1
  459. {
  460. [OperationContract]
  461. int Sum (int a, int b);
  462. [OperationContract (AsyncPattern = true)]
  463. IAsyncResult BeginSum (int a, int b, AsyncCallback cb, object state);
  464. int EndSum (IAsyncResult result);
  465. }
  466. [ServiceContract]
  467. public interface IAsyncMethodNameDoesNotStartWithBegin
  468. {
  469. [OperationContract]
  470. int Sum (int a, int b);
  471. [OperationContract (AsyncPattern = true)]
  472. IAsyncResult StartSum (int a, int b, AsyncCallback cb, object state);
  473. int EndSum (IAsyncResult result);
  474. }
  475. [ServiceContract]
  476. public interface IAsyncNameDoesNotStartWithBeginButExplicitName
  477. {
  478. [OperationContract]
  479. int Sum (int a, int b);
  480. [OperationContract (Name = "Sum", AsyncPattern = true)]
  481. IAsyncResult StartSum (int a, int b, AsyncCallback cb, object state);
  482. int EndSum (IAsyncResult result);
  483. }
  484. [ServiceContract]
  485. public interface IDuplicateOperationNames
  486. {
  487. [OperationContract]
  488. string Echo (string s);
  489. [OperationContract]
  490. string Echo (string s1, string s2);
  491. }
  492. [ServiceContract]
  493. public interface IFooMsgParams
  494. {
  495. [OperationContract (Name = "MyFoo")]
  496. [return: MessageParameter (Name = "MyResult")]
  497. string Foo ([MessageParameter (Name = "MyParam")] string param);
  498. }
  499. [ServiceContract]
  500. public class MessageBodyMemberIsNotInferredService
  501. {
  502. [OperationContract]
  503. public void Echo (MessageBodyMemberIsNotInferredContract msg)
  504. {
  505. }
  506. }
  507. [MessageContract]
  508. public class MessageBodyMemberIsNotInferredContract
  509. {
  510. string foo = "foo";
  511. public string Foo {
  512. get { return foo; }
  513. set { foo = value; }
  514. }
  515. }
  516. }
  517. }