From 97a48b0eab33c3675fed7aee369a51905d86b457 Mon Sep 17 00:00:00 2001 From: Atsushi Eno Date: Wed, 19 Jan 2011 20:22:45 +0900 Subject: [PATCH] Enable duplicate "UriMatched" error check, with couple of FIXMEs. .NET is very unclear about those UriTemplate behavior. Too minor to mind. --- .../WebHttpDispatchOperationSelector.cs | 42 ++++++++++++++-------- .../WebHttpDispatchOperationSelectorTest.cs | 9 +++-- .../Test/System/UriTemplateTest.cs | 16 +++++++++ 3 files changed, 50 insertions(+), 17 deletions(-) diff --git a/mcs/class/System.ServiceModel.Web/System.ServiceModel.Dispatcher/WebHttpDispatchOperationSelector.cs b/mcs/class/System.ServiceModel.Web/System.ServiceModel.Dispatcher/WebHttpDispatchOperationSelector.cs index b9e37a92647..eb4394ccba4 100644 --- a/mcs/class/System.ServiceModel.Web/System.ServiceModel.Dispatcher/WebHttpDispatchOperationSelector.cs +++ b/mcs/class/System.ServiceModel.Web/System.ServiceModel.Dispatcher/WebHttpDispatchOperationSelector.cs @@ -27,6 +27,7 @@ // using System; using System.Collections.Generic; +using System.Linq; using System.ServiceModel; using System.ServiceModel.Channels; using System.ServiceModel.Description; @@ -68,42 +69,53 @@ namespace System.ServiceModel.Dispatcher public string SelectOperation (ref Message message) { - bool dummy; - return SelectOperation (ref message, out dummy); + // FIXME: uriMatched should be used to differentiate 404 and 405 (method not allowed) + bool uriMatched; + return SelectOperation (ref message, out uriMatched); } protected virtual string SelectOperation (ref Message message, out bool uriMatched) { if (message == null) throw new ArgumentNullException ("message"); - // FIXME: something like this check is required here or somewhere else. See WebHttpDispatchOperationSelectorTest.SelectOperationCheckExistingProperty() -// if (message.Properties.ContainsKey (WebBodyFormatMessageProperty.Name)) -// throw new ArgumentException ("There is already message property for Web body format"); + if (message.Properties.ContainsKey (UriMatchedProperty.Name)) + throw new ArgumentException (String.Format ("There is already a message property for template-matched URI '{0}'", UriMatchedProperty.Name)); uriMatched = false; - Uri to = message.Headers.To; - if (to == null) - return String.Empty; + var hp = (HttpRequestMessageProperty) message.Properties [HttpRequestMessageProperty.Name]; + + OperationDescription od = null; + Message dummy = message; // since lambda expression prohibits ref variable... + Uri to = message.Headers.To; // First, UriTemplateTable with corresponding HTTP method is tested. Then other tables can be tested for match. - UriTemplateTable table; - var hp = (HttpRequestMessageProperty) message.Properties [HttpRequestMessageProperty.Name]; - tables.TryGetValue (hp == null ? null : hp.Method, out table); - UriTemplateMatch match = table == null ? null : table.MatchSingle (to); - if (match == null) + UriTemplateTable table = null; + if (hp != null && hp.Method != null) + tables.TryGetValue (hp.Method, out table); + // FIXME: looks like To header does not matter on .NET. (But how to match then? I have no idea) + UriTemplateMatch match = to == null || table == null ? null : table.MatchSingle (to); + if (to != null && match == null) { foreach (var tab in tables.Values) if ((match = tab.MatchSingle (to)) != null) { table = tab; break; } + } - OperationDescription od = null; if (match != null) { uriMatched = true; foreach (TemplateTablePair p in table.KeyValuePairs) if (p.Key == match.Template) od = p.Value as OperationDescription; } - return od != null ? od.Name : String.Empty; + if (od != null) + message.Properties.Add (UriMatchedProperty.Name, new UriMatchedProperty ()); + + return uriMatched && od != null ? od.Name : String.Empty; + } + + internal class UriMatchedProperty + { + public static string Name = "UriMatched"; // this is what .NET uses for MessageProperty that represents a matched URI. } } } diff --git a/mcs/class/System.ServiceModel.Web/Test/System.ServiceModel.Dispatcher/WebHttpDispatchOperationSelectorTest.cs b/mcs/class/System.ServiceModel.Web/Test/System.ServiceModel.Dispatcher/WebHttpDispatchOperationSelectorTest.cs index 039048a3161..d665560d706 100644 --- a/mcs/class/System.ServiceModel.Web/Test/System.ServiceModel.Dispatcher/WebHttpDispatchOperationSelectorTest.cs +++ b/mcs/class/System.ServiceModel.Web/Test/System.ServiceModel.Dispatcher/WebHttpDispatchOperationSelectorTest.cs @@ -133,12 +133,17 @@ namespace MonoTests.System.ServiceModel.Dispatcher [Test] [ExpectedException (typeof (ArgumentException))] - [Category ("NotWorking")] public void SelectOperationCheckExistingProperty () { var d = Create (); - var msg = Message.CreateMessage (MessageVersion.None, "http://temuri.org/MyService/Echo"); + var msg = Message.CreateMessage (MessageVersion.None, "http://temuri.org/MyService/Echo"); // heh, I mistyped it and turned to prove that Action does not matter. + msg.Headers.To = new Uri ("http://localhost:8080/Echo"); + + // LAMESPEC: .NET does returns String.Empty, while we return the name of the operation (as IOperationSelector.SelectOperation is expected to do!) + // Assert.AreEqual (String.Empty, d.SelectOperation (ref msg), "#1"); d.SelectOperation (ref msg); + + // The second invocation should raise the expected exception d.SelectOperation (ref msg); } diff --git a/mcs/class/System.ServiceModel.Web/Test/System/UriTemplateTest.cs b/mcs/class/System.ServiceModel.Web/Test/System/UriTemplateTest.cs index 82105dbec23..db6558a1fb0 100644 --- a/mcs/class/System.ServiceModel.Web/Test/System/UriTemplateTest.cs +++ b/mcs/class/System.ServiceModel.Web/Test/System/UriTemplateTest.cs @@ -320,6 +320,22 @@ namespace MonoTests.System } [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void MatchNullArgument1 () + { + var t = new UriTemplate ("/hooray"); + t.Match (null, new Uri ("http://localhost/")); + } + + [Test] + [ExpectedException (typeof (ArgumentNullException))] + public void MatchNullArgument2 () + { + var t = new UriTemplate ("/hooray"); + t.Match (new Uri ("http://localhost/"), null); + } + + [Test] public void MatchNoTemplateItem () { var t = new UriTemplate ("/hooray"); -- 2.11.4.GIT