3 using System.Runtime.Serialization;
4 using System.ServiceModel;
5 using System.ServiceModel.Channels;
6 using System.ServiceModel.Description;
7 using System.ServiceModel.Dispatcher;
8 using System.ServiceModel.Web;
10 using NUnit.Framework;
12 namespace MonoTests.System.ServiceModel.Description
14 public class WebHttpBehaviorExt : WebHttpBehavior
16 public IClientMessageFormatter DoGetReplyClientFormatter (OperationDescription operationDescription, ServiceEndpoint endpoint)
18 return GetReplyClientFormatter (operationDescription, endpoint);
21 public IClientMessageFormatter DoGetRequestClientFormatter (OperationDescription operationDescription, ServiceEndpoint endpoint)
23 return GetRequestClientFormatter (operationDescription, endpoint);
26 public IDispatchMessageFormatter DoGetReplyDispatchFormatter (OperationDescription operationDescription, ServiceEndpoint endpoint)
28 return GetReplyDispatchFormatter (operationDescription, endpoint);
31 public IDispatchMessageFormatter DoGetRequestDispatchFormatter (OperationDescription operationDescription, ServiceEndpoint endpoint)
33 return GetRequestDispatchFormatter (operationDescription, endpoint);
36 public event Action<ServiceEndpoint, ClientRuntime> ApplyClientBehaviorInvoked;
38 public override void ApplyClientBehavior (ServiceEndpoint endpoint, ClientRuntime client)
40 base.ApplyClientBehavior (endpoint, client);
41 if (ApplyClientBehaviorInvoked != null)
42 ApplyClientBehaviorInvoked (endpoint, client);
47 public class WebHttpBehaviorTest
49 ServiceEndpoint CreateEndpoint ()
51 return new ServiceEndpoint (ContractDescription.GetContract (typeof (IMyService)), new WebHttpBinding (),
52 new EndpointAddress ("http://localhost:37564"));
56 public void DefaultValues ()
58 var b = new WebHttpBehavior ();
59 Assert.AreEqual (WebMessageBodyStyle.Bare, b.DefaultBodyStyle, "#1");
60 Assert.AreEqual (WebMessageFormat.Xml, b.DefaultOutgoingRequestFormat, "#2");
61 Assert.AreEqual (WebMessageFormat.Xml, b.DefaultOutgoingResponseFormat, "#3");
62 Assert.IsFalse (b.AutomaticFormatSelectionEnabled, "#11");
63 Assert.IsFalse (b.FaultExceptionEnabled, "#12");
64 Assert.IsFalse (b.HelpEnabled, "#13");
68 public void AddBiningParameters ()
70 var se = CreateEndpoint ();
71 var b = new WebHttpBehavior ();
72 var pl = new BindingParameterCollection ();
73 b.AddBindingParameters (se, pl);
74 Assert.AreEqual (0, pl.Count, "#1");
79 public void ApplyDispatchBehavior ()
81 var se = CreateEndpoint ();
82 var od = se.Contract.Operations [0];
83 // in .NET 3.5 it adds "OperationSelectorBehavior"
84 int initCB = ContractDescription.GetContract (typeof (IMyService)).Behaviors.Count;
85 // in .NET 3.5 it adds
86 // - OperationInvokeBehavior,
87 // - OperationBehaviorAttribute,
88 // - DataContractSerializerOperationBehavior and
89 // - DataContractSerializerOperationGenerator
90 int initOB = od.Behaviors.Count;
91 // Assert.AreEqual (1, initCB, "#0-1");
92 // Assert.AreEqual (4, initOB, "#0-2");
94 var b = new WebHttpBehavior ();
96 var ed = new EndpointDispatcher (se.Address, se.Contract.Name, se.Contract.Namespace);
97 IChannelListener l = new WebHttpBinding ().BuildChannelListener<IReplyChannel> (new BindingParameterCollection ());
98 var cd = new ChannelDispatcher (l);
99 cd.Endpoints.Add (ed); // without it this test results in NRE (it blindly adds IErrorHandler).
100 Assert.AreEqual (0, cd.ErrorHandlers.Count, "#1-1");
101 Assert.IsNull (ed.DispatchRuntime.OperationSelector, "#1-2");
102 Assert.AreEqual (1, se.Behaviors.Count, "#1-3-1");
103 Assert.AreEqual (initCB, se.Contract.Behaviors.Count, "#1-3-2");
104 Assert.AreEqual (initOB, od.Behaviors.Count, "#1-3-3");
106 Assert.IsTrue (ed.AddressFilter is EndpointAddressMessageFilter, "#1-4");
108 b.ApplyDispatchBehavior (se, ed);
109 // FIXME: implement and enable it later
110 //Assert.AreEqual (1, cd.ErrorHandlers.Count, "#2-1");
111 Assert.AreEqual (typeof (WebHttpDispatchOperationSelector),
112 ed.DispatchRuntime.OperationSelector.GetType (), "#2-2");
113 Assert.AreEqual (1, se.Behaviors.Count, "#3-1");
114 Assert.AreEqual (initCB, se.Contract.Behaviors.Count, "#3-2");
115 Assert.AreEqual (initOB, od.Behaviors.Count, "#3-3");
116 // ... i.e. nothing is added.
118 Assert.IsTrue (ed.AddressFilter is PrefixEndpointAddressMessageFilter, "#3-4");
120 Assert.AreEqual (0, ed.DispatchRuntime.Operations.Count, "#4-0"); // hmm... really?
125 public void GetMessageFormatters ()
127 var se = CreateEndpoint ();
128 var od = se.Contract.Operations [0];
129 var b = new WebHttpBehaviorExt ();
130 Assert.IsNotNull (b.DoGetRequestClientFormatter (od, se), "#1");
131 Assert.IsNotNull (b.DoGetReplyClientFormatter (od, se), "#2");
133 Assert.IsNotNull (b.DoGetRequestDispatchFormatter (od, se), "#3");
134 Assert.IsNotNull (b.DoGetReplyDispatchFormatter (od, se), "#4");
139 public void RequestClientFormatter ()
141 var se = CreateEndpoint ();
142 var od = se.Contract.Operations [0];
143 var b = new WebHttpBehaviorExt ();
144 var rcf = b.DoGetRequestClientFormatter (od, se);
145 var msg = rcf.SerializeRequest (MessageVersion.None, new object [] {"foo"});
146 var hp = msg.Properties [HttpRequestMessageProperty.Name] as HttpRequestMessageProperty;
147 Assert.IsNotNull (hp, "#1");
148 Assert.IsTrue (msg.IsEmpty, "#2");
149 Assert.AreEqual (String.Empty, hp.QueryString, "#3");
150 var mb = msg.CreateBufferedCopy (1000);
152 rcf.DeserializeReply (mb.CreateMessage (), new object [0]);
153 Assert.Fail ("It should not support reply deserialization");
154 } catch (NotSupportedException) {
160 public void RequestClientFormatter2 ()
162 var se = CreateEndpoint ();
163 var od = se.Contract.Operations [0];
164 var b = new WebHttpBehaviorExt ();
165 IClientMessageFormatter rcf = null;
166 b.ApplyClientBehaviorInvoked += delegate (ServiceEndpoint e, ClientRuntime cr) {
167 rcf = cr.Operations [0].Formatter;
169 se.Behaviors.Add (b);
170 var ch = new WebChannelFactory<IMyServiceClient> (se).CreateChannel ();
171 var msg = rcf.SerializeRequest (MessageVersion.None, new object [] {"foo"});
172 var hp = msg.Properties [HttpRequestMessageProperty.Name] as HttpRequestMessageProperty;
173 Assert.IsNotNull (hp, "#1");
174 Assert.IsTrue (msg.IsEmpty, "#2");
175 Assert.AreEqual (String.Empty, hp.QueryString, "#3");
176 //var mb = msg.CreateBufferedCopy (1000);
178 // TODO: test DeserializeReply too (it is supported unlike above).
183 public interface IMyService
187 string Echo (string input);
190 public interface IMyServiceClient : IMyService, IClientChannel
194 public class MyService: IMyService
199 public string Echo (string input)
206 public void TestWebGetExists()
208 ContractDescription cd = ContractDescription.GetContract (typeof(IMyService), typeof (MyService));
209 OperationDescription od = cd.Operations[0];
210 Assert.IsTrue (od.Behaviors.Contains (typeof (WebGetAttribute)), "Operation is recognized as WebGet");
215 public void MessageFormatterSupportsRaw ()
218 var ms = new MemoryStream ();
219 var bytes = new byte [] {0, 1, 2, 0xFF};
220 ms.Write (bytes, 0, bytes.Length);
222 var cd = ContractDescription.GetContract (typeof (ITestService));
223 var od = cd.Operations [0];
224 var se = new ServiceEndpoint (cd, new WebHttpBinding (), new EndpointAddress ("http://localhost:37564/"));
225 var formatter = new WebHttpBehaviorExt ().DoGetReplyDispatchFormatter (od, se);
227 var msg = formatter.SerializeReply (MessageVersion.None, null, ms);
228 var wp = msg.Properties ["WebBodyFormatMessageProperty"] as WebBodyFormatMessageProperty;
229 Assert.IsNotNull (wp, "#1");
230 Assert.AreEqual (WebContentFormat.Raw, wp.Format, "#2");
232 var wmebe = new WebMessageEncodingBindingElement ();
233 var wme = wmebe.CreateMessageEncoderFactory ().Encoder;
234 var ms2 = new MemoryStream ();
235 wme.WriteMessage (msg, ms2);
236 Assert.AreEqual (bytes, ms2.ToArray (), "#3");
240 public void MessageFormatterSupportsRaw2 ()
242 // deserializing request
243 var ms = new MemoryStream ();
244 ms.Write (new byte [] {0, 1, 2, 0xFF}, 0, 4);
246 var cd = ContractDescription.GetContract (typeof (ITestService));
247 var od = cd.Operations [0];
248 var se = new ServiceEndpoint (cd, new WebHttpBinding (), new EndpointAddress ("http://localhost:8080/"));
249 var wmebe = new WebMessageEncodingBindingElement ();
250 var wme = wmebe.CreateMessageEncoderFactory ().Encoder;
251 var msg = wme.ReadMessage (ms, 100, null); // "application/xml" causes error.
252 var formatter = new WebHttpBehaviorExt ().DoGetRequestDispatchFormatter (od, se);
253 object [] pars = new object [1];
254 formatter.DeserializeRequest (msg, pars);
255 Assert.IsTrue (pars [0] is Stream, "ret");
259 public interface IMultipleParametersGet
262 [WebGet (UriTemplate = "get")]
263 void Get (string p1, string p2);
267 public interface IMultipleParameters
270 [WebInvoke (UriTemplate = "posturi?p1={p1}&p2={p2}")]
271 string PostUri (string p1, string p2);
274 [WebInvoke (UriTemplate = "postone?p1={p1}")]
275 string PostOne (string p1, string p2);
278 [WebInvoke (UriTemplate = "postwrapped", BodyStyle=WebMessageBodyStyle.WrappedRequest)]
279 string PostWrapped (string p1, string p2);
282 [WebInvoke (UriTemplate = "out?p1={p1}&p2={p2}", BodyStyle=WebMessageBodyStyle.WrappedResponse)]
283 void PostOut (string p1, string p2, out string ret);
287 public void MultipleParameters ()
289 var behavior = new WebHttpBehaviorExt ();
290 var cd = ContractDescription.GetContract (typeof (IMultipleParameters));
291 var se = new ServiceEndpoint (cd, new WebHttpBinding (), new EndpointAddress ("http://localhost:8080/"));
292 behavior.Validate (se);
294 foreach (var od in cd.Operations)
295 behavior.DoGetRequestClientFormatter (od, se);
299 [Category ("NotWorking")]
300 public void MultipleParameters2 ()
302 var behavior = new WebHttpBehaviorExt ();
303 var cd = ContractDescription.GetContract (typeof (IMultipleParametersGet));
304 var se = new ServiceEndpoint (cd, new WebHttpBinding (), new EndpointAddress ("http://localhost:8080/"));
305 behavior.Validate (se);
308 foreach (var od in cd.Operations)
309 behavior.DoGetRequestClientFormatter (od, se);
310 Assert.Fail ("Should result in invalid operation");
311 } catch (InvalidOperationException) {
317 public interface ITestService
320 Stream Receive (Stream input);