2 // WebHttpDispatchOperationSelectorTest.cs
5 // Atsushi Enomoto <atsushi@ximian.com>
7 // Copyright (C) 2008 Novell, Inc (http://www.novell.com)
8 // Copyright 2011 Xamarin Inc (http://www.xamarin.com).
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System.Globalization;
31 using System.Runtime.Serialization;
32 using System.ServiceModel;
33 using System.ServiceModel.Channels;
34 using System.ServiceModel.Description;
35 using System.ServiceModel.Dispatcher;
36 using System.ServiceModel.Web;
39 using NUnit.Framework;
41 namespace MonoTests.System.ServiceModel.Dispatcher
44 public class WebHttpDispatchOperationSelectorTest
47 [ExpectedException (typeof (ArgumentNullException))]
48 public void ConstructorNullEndpoint ()
50 new WebHttpDispatchOperationSelector (null);
54 [ExpectedException (typeof (InvalidOperationException))]
55 public void ConstructorEndpointNullAddress ()
57 ServiceEndpoint se = new ServiceEndpoint (ContractDescription.GetContract (typeof (MyService)));
58 new WebHttpDispatchOperationSelector (se);
61 #region SelectOperation
64 public void SelectOperation ()
66 SelectOperationCore (Create ());
70 public void SelectOperation2 ()
72 SelectOperationCore (Create2 ());
76 public void SelectOperation3 ()
78 ContractDescription cd = ContractDescription.GetContract (typeof (MyService2));
79 Assert.IsNotNull (cd.Operations [0].Behaviors.Find<WebGetAttribute> (), "#1");
81 cd = ContractDescription.GetContract (typeof (MyService));
82 Assert.IsNull (cd.Operations [0].Behaviors.Find<WebGetAttribute> (), "#2");
85 void SelectOperationCore (MySelector d)
88 var msg = Message.CreateMessage (MessageVersion.Soap12, "http://temuri.org/MyService/Echo"); // looks like Version is not checked
89 Assert.IsNull (msg.Headers.To, "#1-0");
90 Assert.IsFalse (d.SelectOperation (ref msg, out name), "#1");
91 Assert.AreEqual ("", name, "#1-2");
92 Assert.IsNull (msg.Headers.To, "#1-3"); // no overwrite
93 Assert.IsFalse (msg.Properties.ContainsKey ("UriMatched"), "#1-4");
95 msg = Message.CreateMessage (MessageVersion.None, "http://temuri.org/MyService/Echo");
96 Assert.IsFalse (d.SelectOperation (ref msg, out name), "#2");
97 Assert.IsFalse (msg.Properties.ContainsKey ("UriMatched"), "#2-2");
99 msg = Message.CreateMessage (MessageVersion.None, "http://foobar.org/MyService/NonExistent");
100 Assert.IsFalse (d.SelectOperation (ref msg, out name), "#3");
101 Assert.AreEqual ("", name, "#3-2");
102 Assert.IsFalse (msg.Properties.ContainsKey ("UriMatched"), "#3-3");
104 // version and action do not matter
105 msg = Message.CreateMessage (MessageVersion.Soap12, "http://nonexistent.org/");
106 var http = new HttpRequestMessageProperty ();
107 // this mismatch is allowed. Lack of this value is OK.
108 // http.Method = "POST";
109 // this mismatch is allowed. Lack of this value is OK.
110 // http.QueryString = "foo=bar";
111 // this mismatch is allowed. Lack of this value is OK.
112 // http.Headers.Add ("Content-Type", "application/json");
113 // so, the http property can be empty, but is required.
114 msg.Properties.Add (HttpRequestMessageProperty.Name, http);
115 msg.Headers.To = new Uri ("http://localhost:8080/Echo?input=hoge");
116 Assert.IsTrue (d.SelectOperation (ref msg, out name), "#4");
117 // FIXME: hmm... isn'y "Echo" expected?
118 // Assert.AreEqual ("", name, "#4-2");
122 [Category ("NotWorking")]
123 public void SelectOperationOnlyMessage ()
125 // This test shows strange result ... it adds UriMatched property while it does not really match the URI.
128 var msg = Message.CreateMessage (MessageVersion.None, "http://temuri.org/MyService/Echo"); // looks like Version is not checked
129 Assert.AreEqual ("", d.SelectOperation (ref msg), "#1");
130 Assert.IsTrue (msg.Properties.ContainsKey ("UriMatched"), "#1-2");
132 msg = Message.CreateMessage (MessageVersion.None, "http://foobar.org/MyService/NonExistent");
133 Assert.AreEqual ("", d.SelectOperation (ref msg), "#2");
134 Assert.IsNotNull (msg.Properties ["UriMatched"], "#2-2");
138 [ExpectedException (typeof (ArgumentException))]
139 public void SelectOperationCheckExistingProperty ()
142 var msg = Message.CreateMessage (MessageVersion.None, "http://temuri.org/MyService/Echo"); // heh, I mistyped it and turned to prove that Action does not matter.
143 msg.Headers.To = new Uri ("http://localhost:8080/Echo");
145 // LAMESPEC: .NET does returns String.Empty, while we return the name of the operation (as IOperationSelector.SelectOperation is expected to do!)
146 // Assert.AreEqual (String.Empty, d.SelectOperation (ref msg), "#1");
147 d.SelectOperation (ref msg);
149 // The second invocation should raise the expected exception
150 d.SelectOperation (ref msg);
155 class MySelector : WebHttpDispatchOperationSelector
157 public MySelector (ServiceEndpoint se)
162 public bool SelectOperation (ref Message msg, out string name)
165 name = SelectOperation (ref msg, out ret);
170 class MyBehavior : WebHttpBehavior
172 public WebHttpDispatchOperationSelector GetPublicOperationSelector (ServiceEndpoint se)
174 return GetOperationSelector (se);
177 protected override WebHttpDispatchOperationSelector GetOperationSelector (ServiceEndpoint se)
179 return new MySelector (se);
184 public interface MyService
187 // [WebGet (UriTemplate = "MyService/Echo?input={input}")]
188 // [WebGet] // UriTemplate = "Echo?input={input}"
189 string Echo (string input);
192 [ServiceContract (Name = "MyService")]
193 public interface MyService2
195 [OperationContract (Name = "Echo")]
196 [WebGet] // UriTemplate = "Echo?input={input}"
197 string Echo (string input);
202 ServiceEndpoint se = new ServiceEndpoint (ContractDescription.GetContract (typeof (MyService)));
203 se.Address = new EndpointAddress ("http://localhost:8080");
204 se.Contract.Operations [0].Behaviors.Add (new WebGetAttribute ());
205 return new MySelector (se);
206 //var b = new MyBehavior ();
207 //se.Behaviors.Add (b);
208 //return (MySelector) b.GetPublicOperationSelector (se);
211 MySelector Create2 ()
213 ServiceEndpoint se = new ServiceEndpoint (ContractDescription.GetContract (typeof (MyService2)));
214 se.Address = new EndpointAddress ("http://localhost:8080");
215 //se.Contract.Operations [0].Behaviors.Add (new WebGetAttribute ());
216 return new MySelector (se);
221 #region "bug #656020"
227 public string Name { get; set; }
233 [WebGet(UriTemplate = "{name}?age={age}&blah={blah}")]
235 string SayHi (string name, int age, string blah);
237 [WebInvoke(UriTemplate = "blah")]
239 string SayHi2 (User user);
244 public string SayHi (string name, int age, string blah)
246 return string.Format ("Hi {0}: {1}, {2}", name, age, blah == null);
249 public string SayHi2 (User user)
251 return string.Format ("Hi {0}.", user.Name);
256 public void WebMessageFormats ()
258 var host = new WebServiceHost (typeof (Hello));
259 host.AddServiceEndpoint (typeof (IHello), new WebHttpBinding (), "http://localhost:37564/");
260 host.Description.Behaviors.Find<ServiceDebugBehavior> ().IncludeExceptionDetailInFaults = true;
264 using (ChannelFactory<IHello> factory = new ChannelFactory<IHello> (new WebHttpBinding (), "http://localhost:37564/"))
266 factory.Endpoint.Behaviors.Add (new WebHttpBehavior ());
267 IHello h = factory.CreateChannel ();
268 //Console.WriteLine(h.SayHi("Joe", 42, null));
269 Assert.AreEqual ("Hi Joe.", h.SayHi2 (new User { Name = "Joe" }), "#1");