2 using System.Collections.Generic;
4 using System.ServiceModel.Channels;
5 using System.ServiceModel;
6 using System.Reflection;
8 namespace System.ServiceModel.Dispatcher
10 internal class OperationInvokerHandler : BaseRequestProcessorHandler
12 protected override bool ProcessRequest (MessageProcessingContext mrc)
14 RequestContext rc = mrc.RequestContext;
15 DispatchRuntime dispatchRuntime = mrc.OperationContext.EndpointDispatcher.DispatchRuntime;
16 DispatchOperation operation = GetOperation (mrc.IncomingMessage, dispatchRuntime);
17 mrc.Operation = operation;
19 DoProcessRequest (mrc);
20 if (!operation.Invoker.IsSynchronous)
22 } catch (TargetInvocationException ex) {
23 mrc.ReplyMessage = BuildExceptionMessage (mrc.IncomingMessage, ex.InnerException,
24 dispatchRuntime.ChannelDispatcher.IncludeExceptionDetailInFaults);
29 void DoProcessRequest (MessageProcessingContext mrc)
31 DispatchOperation operation = mrc.Operation;
32 Message req = mrc.IncomingMessage;
33 object instance = mrc.InstanceContext.GetServiceInstance(req);
35 BuildInvokeParams (mrc, out parameters);
37 if (operation.Invoker.IsSynchronous) {
38 object result = operation.Invoker.Invoke (instance, parameters);
39 HandleInvokeResult (mrc, parameters, result);
40 } else {// asynchronous
41 InvokeAsynchronous (mrc, instance, parameters);
45 void InvokeAsynchronous (MessageProcessingContext mrc, object instance, object [] parameters)
47 DispatchOperation operation = mrc.Operation;
48 DispatchRuntime dispatchRuntime = mrc.OperationContext.EndpointDispatcher.DispatchRuntime;
49 operation.Invoker.InvokeBegin (instance, parameters,
50 delegate (IAsyncResult res) {
53 result = operation.Invoker.InvokeEnd (instance, out parameters, res);
54 HandleInvokeResult (mrc, parameters, result);
56 } catch (Exception ex) {
57 mrc.ReplyMessage = BuildExceptionMessage (mrc.IncomingMessage, ex, dispatchRuntime.ChannelDispatcher.IncludeExceptionDetailInFaults);
64 DispatchOperation GetOperation (Message input, DispatchRuntime dispatchRuntime)
66 if (dispatchRuntime.OperationSelector != null) {
67 string name = dispatchRuntime.OperationSelector.SelectOperation (ref input);
68 foreach (DispatchOperation d in dispatchRuntime.Operations)
72 string action = input.Headers.Action;
73 foreach (DispatchOperation d in dispatchRuntime.Operations)
74 if (d.Action == action)
77 return dispatchRuntime.UnhandledDispatchOperation;
80 void HandleInvokeResult (MessageProcessingContext mrc, object [] outputs, object result)
82 DispatchOperation operation = mrc.Operation;
83 mrc.EventsHandler.AfterInvoke (operation);
86 if (operation.SerializeReply)
87 res = operation.Formatter.SerializeReply (
88 mrc.OperationContext.EndpointDispatcher.ChannelDispatcher.MessageVersion, outputs, result);
90 res = (Message) result;
91 res.Headers.CopyHeadersFrom (mrc.OperationContext.OutgoingMessageHeaders);
92 res.Properties.CopyProperties (mrc.OperationContext.OutgoingMessageProperties);
93 mrc.ReplyMessage = res;
96 Message CreateActionNotSupported (Message req)
98 FaultCode fc = new FaultCode (
99 req.Version.Addressing.ActionNotSupported,
100 req.Version.Addressing.Namespace);
101 // FIXME: set correct namespace URI
102 return Message.CreateMessage (req.Version, fc,
103 String.Format ("action '{0}' is not supported in this service contract.", req.Headers.Action), String.Empty);
106 void BuildInvokeParams (MessageProcessingContext mrc, out object [] parameters)
108 DispatchOperation operation = mrc.Operation;
109 EnsureValid (operation);
111 if (operation.DeserializeRequest) {
112 parameters = operation.Invoker.AllocateParameters ();
113 operation.Formatter.DeserializeRequest (mrc.IncomingMessage, parameters);
115 parameters = new object [] { mrc.IncomingMessage };
117 mrc.EventsHandler.BeforeInvoke (operation);
120 Message BuildExceptionMessage (Message req, Exception ex, bool includeDetailsInFault)
122 // FIXME: set correct name
123 FaultCode fc = new FaultCode (
124 "InternalServiceFault",
125 req.Version.Addressing.Namespace);
128 if (includeDetailsInFault) {
129 return Message.CreateMessage (req.Version, fc, ex.Message, new ExceptionDetail (ex), req.Headers.Action);
131 // MS returns: The server was unable to process the request due to an internal error. For more information about the error, either turn on IncludeExceptionDetailInFaults (either from ServiceBehaviorAttribute or from the <serviceDebug> configuration behavior) on the server in order to send the exception information back to the client, or turn on tracing as per the Microsoft .NET Framework 3.0 SDK documentation and inspect the server trace logs.";
134 @"The server was unable to process the request due to an internal error. The server may be able to return exception details (it depends on the server settings).";
135 return Message.CreateMessage (req.Version, fc, faultString, req.Headers.Action);
138 void EnsureValid (DispatchOperation operation)
140 if (operation.Invoker == null)
141 throw new InvalidOperationException ("DispatchOperation requires Invoker.");
142 if ((operation.DeserializeRequest || operation.SerializeReply) && operation.Formatter == null)
143 throw new InvalidOperationException ("The DispatchOperation '" + operation.Name + "' requires Formatter, since DeserializeRequest and SerializeReply are not both false.");