Pārlūkot izejas kodu

2010-03-30 Atsushi Enomoto <[email protected]>

	* ChannelDispatcher.cs : differentiate EndpointNotFound and
	  ActionNotSupported so that FaultConverter can create appropriate
	  fault messages. Removed extra filter condition on null To item.
	  And create fault messages on *any* server side error, do not let
	  request client infinitely wait for the response until timeout.

	  (RunDestinationUnreachableTest() is still not working but it works
	  when it is SOAP 1.2.)


svn path=/trunk/mcs/; revision=154439
Atsushi Eno 16 gadi atpakaļ
vecāks
revīzija
a286cc646c

+ 11 - 0
mcs/class/System.ServiceModel/System.ServiceModel.Dispatcher/ChangeLog

@@ -1,3 +1,14 @@
+2010-03-30  Atsushi Enomoto  <[email protected]>
+
+	* ChannelDispatcher.cs : differentiate EndpointNotFound and
+	  ActionNotSupported so that FaultConverter can create appropriate
+	  fault messages. Removed extra filter condition on null To item.
+	  And create fault messages on *any* server side error, do not let
+	  request client infinitely wait for the response until timeout.
+
+	  (RunDestinationUnreachableTest() is still not working but it works
+	  when it is SOAP 1.2.)
+
 2010-03-30  Atsushi Enomoto  <[email protected]>
 
 	* ChannelDispatcher.cs : for faults, use fault namespace, not that of

+ 26 - 39
mcs/class/System.ServiceModel/System.ServiceModel.Dispatcher/ChannelDispatcher.cs

@@ -565,31 +565,21 @@ namespace System.ServiceModel.Dispatcher
 					input.Close ();
 			}
 
-			void SendEndpointNotFound (RequestContext rc, EndpointNotFoundException ex) 
-			{
-				try {
-
-					MessageVersion version = rc.RequestMessage.Version;
-					FaultCode fc = new FaultCode ("DestinationUnreachable", version.Addressing.Namespace);
-					Message res = Message.CreateMessage (version, fc, ex.Message, rc.RequestMessage.Version.Addressing.FaultNamespace);
-					rc.Reply (res);
-				} catch (Exception e) {
-					// FIXME: log it
-					Console.WriteLine ("Error on sending DestinationUnreachable fault message: " + e);
-				}
-			}
-
 			void ProcessRequest (IReplyChannel reply, RequestContext rc)
 			{
+				var req = rc.RequestMessage;
 				try {
-					EndpointDispatcher candidate = FindEndpointDispatcher (rc.RequestMessage);
-					new InputOrReplyRequestProcessor (candidate.DispatchRuntime, reply).
-						ProcessReply (rc);
-				} catch (EndpointNotFoundException ex) {
-					SendEndpointNotFound (rc, ex);
+					var ed = FindEndpointDispatcher (req);
+					new InputOrReplyRequestProcessor (ed.DispatchRuntime, reply).ProcessReply (rc);
 				} catch (Exception ex) {
 					// FIXME: log it.
 					Console.WriteLine (ex);
+
+					var conv = reply.GetProperty<FaultConverter> () ?? FaultConverter.GetDefaultFaultConverter (rc.RequestMessage.Version);
+					Message res;
+					if (!conv.TryCreateFaultMessage (ex, out res))
+						res = Message.CreateMessage (req.Version, new FaultCode ("Receiver"), ex.Message, req.Version.Addressing.FaultNamespace);
+					rc.Reply (res);
 				} finally {
 					if (rc != null)
 						rc.Close ();
@@ -619,33 +609,30 @@ namespace System.ServiceModel.Dispatcher
 
 			EndpointDispatcher FindEndpointDispatcher (Message message) {
 				EndpointDispatcher candidate = null;
-				for (int i = 0; i < owner.Endpoints.Count; i++) {
-					if (MessageMatchesEndpointDispatcher (message, owner.Endpoints [i])) {
-						var newdis = owner.Endpoints [i];
+				bool hasEndpointMatch = false;
+				foreach (var endpoint in owner.Endpoints) {
+					if (endpoint.AddressFilter.Match (message)) {
+						hasEndpointMatch = true;
+						if (!endpoint.ContractFilter.Match (message))
+							continue;
+						var newdis = endpoint;
 						if (candidate == null || candidate.FilterPriority < newdis.FilterPriority)
 							candidate = newdis;
 						else if (candidate.FilterPriority == newdis.FilterPriority)
 							throw new MultipleFilterMatchesException ();
 					}
 				}
-				if (candidate == null && owner.Host != null)
-					owner.Host.OnUnknownMessageReceived (message);
-				return candidate;
-			}
+				if (candidate == null && !hasEndpointMatch) {
+					if (owner.Host != null)
+						owner.Host.OnUnknownMessageReceived (message);
+					// we have to return a fault to the client anyways...
+					throw new EndpointNotFoundException ();
+				}
+				else if (candidate == null)
+					// FIXME: It is not a good place to check, but anyways detach this error from EndpointNotFoundException.
+					throw new ActionNotSupportedException (String.Format ("Action '{0}' did not match any operations in the target contract", message.Headers.Action));
 
-			// FIXME: this part needs refactoring.
-			// First, Endpoint must be identified, or return EndpointNotFound fault in case address filter didn't match anything.
-			// Then, contract filter must be applied to identify a dispatch operation, or return ActionNotSupported fault in case contract filter didn't match anything.
-			bool MessageMatchesEndpointDispatcher (Message req, EndpointDispatcher endpoint)
-			{
-				// FIXME: handle AddressFilterMode.Prefix too.
-
-				Uri to = req.Headers.To;
-				if (to == null)
-					return address_filter_mode == AddressFilterMode.Any;
-				if (to.AbsoluteUri == Constants.WsaAnonymousUri)
-					return false;
-				return endpoint.AddressFilter.Match (req) && endpoint.ContractFilter.Match (req);
+				return candidate;
 			}
 		}
 }