1 //------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 //------------------------------------------------------------
4 #pragma warning disable 1634, 1691
5 namespace System.ServiceModel.Description
8 using System.Collections.Generic;
9 using System.Collections.ObjectModel;
10 using System.ComponentModel;
13 using System.ServiceModel;
14 using System.ServiceModel.Administration;
15 using System.ServiceModel.Channels;
16 using System.ServiceModel.Dispatcher;
17 using System.ServiceModel.Web;
19 public class WebHttpBehavior : IEndpointBehavior, IWmiInstanceProvider
21 internal const string GET = "GET";
22 internal const string POST = "POST";
23 internal const string WildcardAction = "*";
24 internal const string WildcardMethod = "*";
25 internal static readonly string defaultStreamContentType = "application/octet-stream";
26 internal static readonly string defaultCallbackParameterName = "callback";
27 const string AddressPropertyName = "Address";
28 WebMessageBodyStyle defaultBodyStyle;
29 WebMessageFormat defaultOutgoingReplyFormat;
30 WebMessageFormat defaultOutgoingRequestFormat;
31 XmlSerializerOperationBehavior.Reflector reflector;
32 UnwrappedTypesXmlSerializerManager xmlSerializerManager;
34 public WebHttpBehavior()
36 defaultOutgoingRequestFormat = WebMessageFormat.Xml;
37 defaultOutgoingReplyFormat = WebMessageFormat.Xml;
38 this.defaultBodyStyle = WebMessageBodyStyle.Bare;
39 xmlSerializerManager = new UnwrappedTypesXmlSerializerManager();
42 internal delegate void Effect();
44 public virtual WebMessageBodyStyle DefaultBodyStyle
46 get { return this.defaultBodyStyle; }
49 if (!WebMessageBodyStyleHelper.IsDefined(value))
51 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value"));
53 this.defaultBodyStyle = value;
57 public virtual WebMessageFormat DefaultOutgoingRequestFormat
61 return this.defaultOutgoingRequestFormat;
65 if (!WebMessageFormatHelper.IsDefined(value))
67 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value"));
69 this.defaultOutgoingRequestFormat = value;
73 public virtual WebMessageFormat DefaultOutgoingResponseFormat
77 return this.defaultOutgoingReplyFormat;
81 if (!WebMessageFormatHelper.IsDefined(value))
83 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value"));
85 this.defaultOutgoingReplyFormat = value;
89 public virtual bool HelpEnabled { get; set; }
91 public virtual bool AutomaticFormatSelectionEnabled { get; set; }
93 public virtual bool FaultExceptionEnabled { get; set; }
95 internal Uri HelpUri { get; set; }
97 protected internal string JavascriptCallbackParameterName { get; set; }
99 public virtual void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
104 public virtual void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
106 if (endpoint == null)
108 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpoint");
110 if (clientRuntime == null)
112 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("clientRuntime");
114 WebMessageEncodingBindingElement webEncodingBindingElement = endpoint.Binding.CreateBindingElements().Find<WebMessageEncodingBindingElement>();
115 if (webEncodingBindingElement != null && webEncodingBindingElement.CrossDomainScriptAccessEnabled)
117 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR2.CrossDomainJavascriptNotsupported));
119 #pragma warning disable 56506 // Microsoft, endpoint.Contract is never null
120 this.reflector = new XmlSerializerOperationBehavior.Reflector(endpoint.Contract.Namespace, null);
121 foreach (OperationDescription od in endpoint.Contract.Operations)
122 #pragma warning restore 56506
124 #pragma warning disable 56506 // Microsoft, clientRuntime.Operations is never null
125 if (clientRuntime.Operations.Contains(od.Name))
126 #pragma warning restore 56506
128 ClientOperation cop = clientRuntime.Operations[od.Name];
129 IClientMessageFormatter requestClient = GetRequestClientFormatter(od, endpoint);
130 IClientMessageFormatter replyClient = GetReplyClientFormatter(od, endpoint);
131 cop.Formatter = new CompositeClientFormatter(requestClient, replyClient);
132 cop.SerializeRequest = true;
133 cop.DeserializeReply = od.Messages.Count > 1 && !IsUntypedMessage(od.Messages[1]);
136 AddClientErrorInspector(endpoint, clientRuntime);
139 public virtual void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
141 if (endpoint == null)
143 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpoint");
145 if (endpointDispatcher == null)
147 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpointDispatcher");
149 WebMessageEncodingBindingElement webEncodingBindingElement = endpoint.Binding.CreateBindingElements().Find<WebMessageEncodingBindingElement>();
150 if (webEncodingBindingElement != null && webEncodingBindingElement.CrossDomainScriptAccessEnabled)
152 ISecurityCapabilities securityCapabilities = endpoint.Binding.GetProperty<ISecurityCapabilities>(new BindingParameterCollection());
153 if (securityCapabilities.SupportsClientAuthentication)
155 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR2.CrossDomainJavascriptAuthNotSupported));
157 if (endpoint.Contract.Behaviors.Contains(typeof(JavascriptCallbackBehaviorAttribute)))
159 JavascriptCallbackBehaviorAttribute behavior = endpoint.Contract.Behaviors[typeof(JavascriptCallbackBehaviorAttribute)] as JavascriptCallbackBehaviorAttribute;
160 this.JavascriptCallbackParameterName = behavior.UrlParameterName;
164 this.JavascriptCallbackParameterName = defaultCallbackParameterName;
166 endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new JavascriptCallbackMessageInspector(this.JavascriptCallbackParameterName));
168 if (this.HelpEnabled)
170 this.HelpUri = new UriTemplate(HelpPage.OperationListHelpPageUriTemplate).BindByPosition(endpoint.ListenUri);
172 #pragma warning disable 56506 // Microsoft, endpoint.Contract is never null
173 this.reflector = new XmlSerializerOperationBehavior.Reflector(endpoint.Contract.Namespace, null);
174 #pragma warning restore 56506
177 endpointDispatcher.AddressFilter = new PrefixEndpointAddressMessageFilter(endpoint.Address);
178 endpointDispatcher.ContractFilter = new MatchAllMessageFilter();
179 // operation selector
180 #pragma warning disable 56506 // Microsoft, endpointDispatcher.DispatchRuntime is never null
181 endpointDispatcher.DispatchRuntime.OperationSelector = this.GetOperationSelector(endpoint);
182 #pragma warning restore 56506
183 // unhandled operation
184 string actionStarOperationName = null;
185 #pragma warning disable 56506 // Microsoft, endpoint.Contract is never null
186 foreach (OperationDescription od in endpoint.Contract.Operations)
187 #pragma warning restore 56506
189 if (od.Messages[0].Direction == MessageDirection.Input
190 && od.Messages[0].Action == WildcardAction)
192 actionStarOperationName = od.Name;
196 if (actionStarOperationName != null)
198 // WCF v1 installs any Action="*" op into UnhandledDispatchOperation, but WebHttpBehavior
199 // doesn't want this, so we 'move' that operation back into normal set of operations
200 #pragma warning disable 56506 // Microsoft, endpointDispatcher.DispatchRuntime.{Operations,UnhandledDispatchOperation} is never null
201 endpointDispatcher.DispatchRuntime.Operations.Add(
202 endpointDispatcher.DispatchRuntime.UnhandledDispatchOperation);
203 #pragma warning restore 56506
206 FormatSelectingMessageInspector formatSelectingMessageInspector = null;
207 string xmlContentType = null;
208 string jsonContentType = null;
211 if (webEncodingBindingElement != null)
213 XmlFormatMapping xmlFormatMapping = new XmlFormatMapping(webEncodingBindingElement.WriteEncoding, webEncodingBindingElement.ContentTypeMapper);
214 JsonFormatMapping jsonFormatMapping = new JsonFormatMapping(webEncodingBindingElement.WriteEncoding, webEncodingBindingElement.ContentTypeMapper);
216 xmlContentType = xmlFormatMapping.DefaultContentType.ToString();
217 jsonContentType = jsonFormatMapping.DefaultContentType.ToString();
219 if (AutomaticFormatSelectionEnabled)
221 formatSelectingMessageInspector = new FormatSelectingMessageInspector(this, new List<MultiplexingFormatMapping> { xmlFormatMapping, jsonFormatMapping });
222 endpointDispatcher.DispatchRuntime.MessageInspectors.Add(formatSelectingMessageInspector);
227 xmlContentType = TextMessageEncoderFactory.GetContentType(XmlFormatMapping.defaultMediaType, TextEncoderDefaults.Encoding);
228 jsonContentType = JsonMessageEncoderFactory.GetContentType(null);
231 #pragma warning disable 56506 // Microsoft, endpointDispatcher.DispatchRuntime.UnhandledDispatchOperation is never null
232 // always install UnhandledDispatchOperation (WebHttpDispatchOperationSelector may choose not to use it)
233 endpointDispatcher.DispatchRuntime.UnhandledDispatchOperation = new DispatchOperation(endpointDispatcher.DispatchRuntime, "*", WildcardAction, WildcardAction);
234 endpointDispatcher.DispatchRuntime.UnhandledDispatchOperation.DeserializeRequest = false;
235 endpointDispatcher.DispatchRuntime.UnhandledDispatchOperation.SerializeReply = false;
236 endpointDispatcher.DispatchRuntime.UnhandledDispatchOperation.Invoker = new HttpUnhandledOperationInvoker { HelpUri = this.HelpUri };
237 #pragma warning restore 56506
238 // install formatters and parameter inspectors
239 foreach (OperationDescription od in endpoint.Contract.Operations)
241 DispatchOperation dop = null;
242 #pragma warning disable 56506 // Microsoft, endpointDispatcher.DispatchRuntime, DispatchRuntime.Operations are never null
243 if (endpointDispatcher.DispatchRuntime.Operations.Contains(od.Name))
244 #pragma warning restore 56506
246 dop = endpointDispatcher.DispatchRuntime.Operations[od.Name];
248 #pragma warning disable 56506 // Microsoft, endpointDispatcher.DispatchRuntime.UnhandledDispatchOperation is never null
249 else if (endpointDispatcher.DispatchRuntime.UnhandledDispatchOperation.Name == od.Name)
251 dop = endpointDispatcher.DispatchRuntime.UnhandledDispatchOperation;
253 #pragma warning restore 56506
256 IDispatchMessageFormatter requestDispatch = GetRequestDispatchFormatter(od, endpoint);
257 IDispatchMessageFormatter replyDispatch = GetReplyDispatchFormatter(od, endpoint);
259 MultiplexingDispatchMessageFormatter replyDispatchAsMultiplexing = replyDispatch as MultiplexingDispatchMessageFormatter;
261 if (replyDispatchAsMultiplexing != null)
263 // here we are adding all default content types, despite the fact that
264 // some of the formatters in MultiplexingDispatchMessageFormatter might not be present
265 // i.e. the JSON formatter
267 replyDispatchAsMultiplexing.DefaultContentTypes.Add(WebMessageFormat.Xml, xmlContentType);
268 replyDispatchAsMultiplexing.DefaultContentTypes.Add(WebMessageFormat.Json, jsonContentType);
270 if (formatSelectingMessageInspector != null)
272 formatSelectingMessageInspector.RegisterOperation(od.Name, replyDispatchAsMultiplexing);
276 dop.Formatter = new CompositeDispatchFormatter(requestDispatch, replyDispatch);
277 dop.FaultFormatter = new WebFaultFormatter(dop.FaultFormatter);
278 dop.DeserializeRequest = (requestDispatch != null);
279 dop.SerializeReply = od.Messages.Count > 1 && (replyDispatch != null);
283 if (this.HelpEnabled)
285 HelpPage helpPage = new HelpPage(this, endpoint.Contract);
286 DispatchOperation dispatchOperation = new DispatchOperation(endpointDispatcher.DispatchRuntime, HelpOperationInvoker.OperationName, null, null)
288 DeserializeRequest = false,
289 SerializeReply = false,
290 Invoker = new HelpOperationInvoker(helpPage, endpointDispatcher.DispatchRuntime.UnhandledDispatchOperation.Invoker),
292 endpointDispatcher.DispatchRuntime.Operations.Add(dispatchOperation);
294 AddServerErrorHandlers(endpoint, endpointDispatcher);
297 internal virtual Dictionary<string, string> GetWmiProperties()
299 Dictionary<string, string> result = new Dictionary<string, string>();
300 result.Add("DefaultBodyStyle", this.DefaultBodyStyle.ToString());
301 result.Add("DefaultOutgoingRequestFormat", this.DefaultOutgoingRequestFormat.ToString());
302 result.Add("DefaultOutgoingResponseFormat", this.DefaultOutgoingResponseFormat.ToString());
306 internal virtual string GetWmiTypeName()
308 return "WebHttpBehavior";
311 void IWmiInstanceProvider.FillInstance(IWmiInstance wmiInstance)
313 if (wmiInstance == null)
315 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("wmiInstance");
317 Dictionary<string, string> properties = this.GetWmiProperties();
318 foreach (string key in properties.Keys)
320 wmiInstance.SetProperty(key, properties[key]);
324 string IWmiInstanceProvider.GetInstanceType()
326 return GetWmiTypeName();
329 public virtual void Validate(ServiceEndpoint endpoint)
331 if (endpoint == null)
333 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpoint");
335 ValidateNoMessageHeadersPresent(endpoint);
336 ValidateBinding(endpoint);
337 ValidateContract(endpoint);
340 void ValidateNoMessageHeadersPresent(ServiceEndpoint endpoint)
342 if (endpoint == null || endpoint.Address == null)
346 EndpointAddress address = endpoint.Address;
347 if (address.Headers.Count > 0)
349 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR2.GetString(SR2.WebHttpServiceEndpointCannotHaveMessageHeaders, address)));
353 protected virtual void ValidateBinding(ServiceEndpoint endpoint)
355 ValidateIsWebHttpBinding(endpoint, this.GetType().ToString());
358 internal static string GetWebMethod(OperationDescription od)
360 WebGetAttribute wga = od.Behaviors.Find<WebGetAttribute>();
361 WebInvokeAttribute wia = od.Behaviors.Find<WebInvokeAttribute>();
362 EnsureOk(wga, wia, od);
367 else if (wia != null)
369 return wia.Method ?? POST;
377 internal static string GetWebUriTemplate(OperationDescription od)
379 // return exactly what is on the attribute
380 WebGetAttribute wga = od.Behaviors.Find<WebGetAttribute>();
381 WebInvokeAttribute wia = od.Behaviors.Find<WebInvokeAttribute>();
382 EnsureOk(wga, wia, od);
385 return wga.UriTemplate;
387 else if (wia != null)
389 return wia.UriTemplate;
397 internal static string GetDescription(OperationDescription od)
399 object[] attributes = null;
400 if (od.SyncMethod != null)
402 attributes = od.SyncMethod.GetCustomAttributes(typeof(DescriptionAttribute), true);
404 else if (od.BeginMethod != null)
406 attributes = od.BeginMethod.GetCustomAttributes(typeof(DescriptionAttribute), true);
409 if (attributes != null && attributes.Length > 0)
411 return ((DescriptionAttribute)attributes[0]).Description;
419 internal static bool IsTypedMessage(MessageDescription message)
421 return (message != null && message.MessageType != null);
424 internal static bool IsUntypedMessage(MessageDescription message)
430 return (message.Body.ReturnValue != null && message.Body.Parts.Count == 0 && message.Body.ReturnValue.Type == typeof(Message)) ||
431 (message.Body.ReturnValue == null && message.Body.Parts.Count == 1 && message.Body.Parts[0].Type == typeof(Message));
434 internal static MessageDescription MakeDummyMessageDescription(MessageDirection direction)
436 MessageDescription messageDescription = new MessageDescription("urn:dummyAction", direction);
437 return messageDescription;
440 internal static bool SupportsJsonFormat(OperationDescription od)
442 // if the type is XmlSerializable, then we cannot create a json serializer for it
443 DataContractSerializerOperationBehavior dcsob = od.Behaviors.Find<DataContractSerializerOperationBehavior>();
444 return (dcsob != null);
447 internal static void ValidateIsWebHttpBinding(ServiceEndpoint serviceEndpoint, string behaviorName)
449 Binding binding = serviceEndpoint.Binding;
450 if (binding.Scheme != "http" && binding.Scheme != "https")
452 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
453 SR2.GetString(SR2.WCFBindingCannotBeUsedWithUriOperationSelectorBehaviorBadScheme,
454 serviceEndpoint.Contract.Name, behaviorName)));
456 if (binding.MessageVersion != MessageVersion.None)
458 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
459 SR2.GetString(SR2.WCFBindingCannotBeUsedWithUriOperationSelectorBehaviorBadMessageVersion,
460 serviceEndpoint.Address.Uri.AbsoluteUri, behaviorName)));
462 TransportBindingElement transportBindingElement = binding.CreateBindingElements().Find<TransportBindingElement>();
463 if (transportBindingElement != null && !transportBindingElement.ManualAddressing)
465 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
466 SR2.GetString(SR2.ManualAddressingCannotBeFalseWithTransportBindingElement,
467 serviceEndpoint.Address.Uri.AbsoluteUri, behaviorName, transportBindingElement.GetType().Name)));
471 internal WebMessageBodyStyle GetBodyStyle(OperationDescription od)
473 WebGetAttribute wga = od.Behaviors.Find<WebGetAttribute>();
474 WebInvokeAttribute wia = od.Behaviors.Find<WebInvokeAttribute>();
475 EnsureOk(wga, wia, od);
478 return wga.GetBodyStyleOrDefault(this.DefaultBodyStyle);
480 else if (wia != null)
482 return wia.GetBodyStyleOrDefault(this.DefaultBodyStyle);
486 return this.DefaultBodyStyle;
490 internal IClientMessageFormatter GetDefaultClientFormatter(OperationDescription od, bool useJson, bool isWrapped)
492 DataContractSerializerOperationBehavior dcsob = od.Behaviors.Find<DataContractSerializerOperationBehavior>();
497 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR2.GetString(SR2.JsonFormatRequiresDataContract, od.Name, od.DeclaringContract.Name, od.DeclaringContract.Namespace)));
499 return CreateDataContractJsonSerializerOperationFormatter(od, dcsob, isWrapped);
503 ClientRuntime clientRuntime = new ClientRuntime("name", "");
504 ClientOperation cop = new ClientOperation(clientRuntime, "dummyClient", "urn:dummy");
505 cop.Formatter = null;
509 (dcsob as IOperationBehavior).ApplyClientBehavior(od, cop);
510 return cop.Formatter;
512 XmlSerializerOperationBehavior xsob = od.Behaviors.Find<XmlSerializerOperationBehavior>();
515 xsob = new XmlSerializerOperationBehavior(od, xsob.XmlSerializerFormatAttribute, this.reflector);
516 (xsob as IOperationBehavior).ApplyClientBehavior(od, cop);
517 return cop.Formatter;
523 protected virtual void AddClientErrorInspector(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
525 if (!this.FaultExceptionEnabled)
527 clientRuntime.MessageInspectors.Add(new WebFaultClientMessageInspector());
531 clientRuntime.MessageVersionNoneFaultsEnabled = true;
535 protected virtual void AddServerErrorHandlers(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
537 if (!this.FaultExceptionEnabled)
539 WebErrorHandler errorHandler = new WebErrorHandler(this, endpoint.Contract, endpointDispatcher.DispatchRuntime.ChannelDispatcher.IncludeExceptionDetailInFaults);
540 endpointDispatcher.DispatchRuntime.ChannelDispatcher.ErrorHandlers.Add(errorHandler);
544 protected virtual WebHttpDispatchOperationSelector GetOperationSelector(ServiceEndpoint endpoint)
546 return new WebHttpDispatchOperationSelector(endpoint);
549 protected virtual QueryStringConverter GetQueryStringConverter(OperationDescription operationDescription)
551 return new QueryStringConverter();
554 protected virtual IClientMessageFormatter GetReplyClientFormatter(OperationDescription operationDescription, ServiceEndpoint endpoint)
556 if (operationDescription.Messages.Count < 2)
560 ValidateBodyParameters(operationDescription, false);
562 if (TryGetStreamParameterType(operationDescription.Messages[1], operationDescription, false, out type))
564 return new HttpStreamFormatter(operationDescription);
566 if (IsUntypedMessage(operationDescription.Messages[1]))
568 return new MessagePassthroughFormatter();
570 WebMessageBodyStyle style = GetBodyStyle(operationDescription);
572 if (UseBareReplyFormatter(style, operationDescription, GetResponseFormat(operationDescription), out parameterType))
574 return SingleBodyParameterMessageFormatter.CreateXmlAndJsonClientFormatter(operationDescription, parameterType, false, this.xmlSerializerManager);
578 MessageDescription temp = operationDescription.Messages[0];
579 operationDescription.Messages[0] = MakeDummyMessageDescription(MessageDirection.Input);
580 IClientMessageFormatter result;
581 result = GetDefaultXmlAndJsonClientFormatter(operationDescription, !IsBareResponse(style));
582 operationDescription.Messages[0] = temp;
587 internal virtual bool UseBareReplyFormatter(WebMessageBodyStyle style, OperationDescription operationDescription, WebMessageFormat responseFormat, out Type parameterType)
589 parameterType = null;
590 return IsBareResponse(style) && TryGetNonMessageParameterType(operationDescription.Messages[1], operationDescription, false, out parameterType);
593 protected virtual IDispatchMessageFormatter GetReplyDispatchFormatter(OperationDescription operationDescription, ServiceEndpoint endpoint)
595 if (operationDescription.Messages.Count < 2)
599 ValidateBodyParameters(operationDescription, false);
600 WebMessageFormat responseFormat = GetResponseFormat(operationDescription);
602 // Determine if we should add a json formatter; If the ResponseFormat is json, we always add the json formatter even if the
603 // operation is XmlSerializerFormat because the formatter constructor throws the exception: "json not valid with XmlSerializerFormat" [Microsoft]
604 bool useJson = (responseFormat == WebMessageFormat.Json || SupportsJsonFormat(operationDescription));
606 IDispatchMessageFormatter innerFormatter;
609 if (TryGetStreamParameterType(operationDescription.Messages[1], operationDescription, false, out type))
611 innerFormatter = new ContentTypeSettingDispatchMessageFormatter(defaultStreamContentType, new HttpStreamFormatter(operationDescription));
613 else if (IsUntypedMessage(operationDescription.Messages[1]))
615 innerFormatter = new MessagePassthroughFormatter();
620 WebMessageBodyStyle style = GetBodyStyle(operationDescription);
621 Dictionary<WebMessageFormat, IDispatchMessageFormatter> formatters = new Dictionary<WebMessageFormat, IDispatchMessageFormatter>();
623 if (UseBareReplyFormatter(style, operationDescription, responseFormat, out parameterType))
625 formatters.Add(WebMessageFormat.Xml, SingleBodyParameterMessageFormatter.CreateDispatchFormatter(operationDescription, parameterType, false, false, this.xmlSerializerManager, null));
628 formatters.Add(WebMessageFormat.Json, SingleBodyParameterMessageFormatter.CreateDispatchFormatter(operationDescription, parameterType, false, true, this.xmlSerializerManager, this.JavascriptCallbackParameterName));
633 MessageDescription temp = operationDescription.Messages[0];
634 operationDescription.Messages[0] = MakeDummyMessageDescription(MessageDirection.Input);
635 formatters.Add(WebMessageFormat.Xml, GetDefaultDispatchFormatter(operationDescription, false, !IsBareResponse(style)));
638 formatters.Add(WebMessageFormat.Json, GetDefaultDispatchFormatter(operationDescription, true, !IsBareResponse(style)));
640 operationDescription.Messages[0] = temp;
642 innerFormatter = new MultiplexingDispatchMessageFormatter(formatters, responseFormat);
645 return innerFormatter;
648 protected virtual IClientMessageFormatter GetRequestClientFormatter(OperationDescription operationDescription, ServiceEndpoint endpoint)
650 WebMessageFormat requestFormat = GetRequestFormat(operationDescription);
651 bool useJson = (requestFormat == WebMessageFormat.Json);
652 WebMessageEncodingBindingElement webEncoding = (useJson) ? endpoint.Binding.CreateBindingElements().Find<WebMessageEncodingBindingElement>() : null;
653 IClientMessageFormatter innerFormatter = null;
655 // get some validation errors by creating "throwAway" formatter
657 // validate that endpoint.Address is not null before accessing the endpoint.Address.Uri. This is to avoid throwing a NullRefException while constructing a UriTemplateClientFormatter
658 if (endpoint.Address == null)
660 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
661 SR2.GetString(SR2.ServiceEndpointMustHaveNonNullAddress, typeof(ServiceEndpoint), typeof(ChannelFactory), typeof(WebHttpEndpoint), AddressPropertyName, typeof(ServiceEndpoint))));
664 UriTemplateClientFormatter throwAway = new UriTemplateClientFormatter(operationDescription, null, GetQueryStringConverter(operationDescription), endpoint.Address.Uri, false, endpoint.Contract.Name);
665 int numUriVariables = throwAway.pathMapping.Count + throwAway.queryMapping.Count;
666 bool isStream = false;
667 HideReplyMessage(operationDescription, delegate()
669 WebMessageBodyStyle style = GetBodyStyle(operationDescription);
670 bool isUntypedWhenUriParamsNotConsidered = false;
671 Effect doBodyFormatter = delegate()
673 if (numUriVariables != 0)
675 EnsureNotUntypedMessageNorMessageContract(operationDescription);
677 // get body formatter
678 ValidateBodyParameters(operationDescription, true);
679 IClientMessageFormatter baseFormatter;
681 if (TryGetStreamParameterType(operationDescription.Messages[0], operationDescription, true, out parameterType))
684 baseFormatter = new HttpStreamFormatter(operationDescription);
686 else if (UseBareRequestFormatter(style, operationDescription, out parameterType))
688 baseFormatter = SingleBodyParameterMessageFormatter.CreateClientFormatter(operationDescription, parameterType, true, useJson, this.xmlSerializerManager);
692 baseFormatter = GetDefaultClientFormatter(operationDescription, useJson, !IsBareRequest(style));
694 innerFormatter = baseFormatter;
695 isUntypedWhenUriParamsNotConsidered = IsUntypedMessage(operationDescription.Messages[0]);
697 if (numUriVariables == 0)
699 if (IsUntypedMessage(operationDescription.Messages[0]))
701 ValidateBodyParameters(operationDescription, true);
702 innerFormatter = new MessagePassthroughFormatter();
703 isUntypedWhenUriParamsNotConsidered = true;
705 else if (IsTypedMessage(operationDescription.Messages[0]))
707 ValidateBodyParameters(operationDescription, true);
708 innerFormatter = GetDefaultClientFormatter(operationDescription, useJson, !IsBareRequest(style));
717 HideRequestUriTemplateParameters(operationDescription, throwAway, delegate()
719 CloneMessageDescriptionsBeforeActing(operationDescription, delegate()
725 innerFormatter = new UriTemplateClientFormatter(operationDescription, innerFormatter, GetQueryStringConverter(operationDescription), endpoint.Address.Uri, isUntypedWhenUriParamsNotConsidered, endpoint.Contract.Name);
727 string defaultContentType = GetDefaultContentType(isStream, useJson, webEncoding);
728 if (!string.IsNullOrEmpty(defaultContentType))
730 innerFormatter = new ContentTypeSettingClientMessageFormatter(defaultContentType, innerFormatter);
732 return innerFormatter;
735 protected virtual IDispatchMessageFormatter GetRequestDispatchFormatter(OperationDescription operationDescription, ServiceEndpoint endpoint)
737 IDispatchMessageFormatter result = null;
738 // get some validation errors by creating "throwAway" formatter
739 UriTemplateDispatchFormatter throwAway = new UriTemplateDispatchFormatter(operationDescription, null, GetQueryStringConverter(operationDescription), endpoint.Contract.Name, endpoint.Address.Uri);
740 int numUriVariables = throwAway.pathMapping.Count + throwAway.queryMapping.Count;
741 HideReplyMessage(operationDescription, delegate()
743 WebMessageBodyStyle style = GetBodyStyle(operationDescription);
744 Effect doBodyFormatter = delegate()
746 if (numUriVariables != 0)
748 EnsureNotUntypedMessageNorMessageContract(operationDescription);
750 // get body formatter
751 ValidateBodyParameters(operationDescription, true);
753 if (TryGetStreamParameterType(operationDescription.Messages[0], operationDescription, true, out type))
755 result = new HttpStreamFormatter(operationDescription);
760 if (UseBareRequestFormatter(style, operationDescription, out parameterType))
762 result = SingleBodyParameterMessageFormatter.CreateXmlAndJsonDispatchFormatter(operationDescription, parameterType, true, this.xmlSerializerManager, this.JavascriptCallbackParameterName);
766 result = GetDefaultXmlAndJsonDispatchFormatter(operationDescription, !IsBareRequest(style));
770 if (numUriVariables == 0)
772 if (IsUntypedMessage(operationDescription.Messages[0]))
774 ValidateBodyParameters(operationDescription, true);
775 result = new MessagePassthroughFormatter();
777 else if (IsTypedMessage(operationDescription.Messages[0]))
779 ValidateBodyParameters(operationDescription, true);
780 result = GetDefaultXmlAndJsonDispatchFormatter(operationDescription, !IsBareRequest(style));
789 HideRequestUriTemplateParameters(operationDescription, throwAway, delegate()
791 CloneMessageDescriptionsBeforeActing(operationDescription, delegate()
797 result = new UriTemplateDispatchFormatter(operationDescription, result, GetQueryStringConverter(operationDescription), endpoint.Contract.Name, endpoint.Address.Uri);
802 static void CloneMessageDescriptionsBeforeActing(OperationDescription operationDescription, Effect effect)
804 MessageDescription originalRequest = operationDescription.Messages[0];
805 bool thereIsAReply = operationDescription.Messages.Count > 1;
806 MessageDescription originalReply = thereIsAReply ? operationDescription.Messages[1] : null;
807 operationDescription.Messages[0] = originalRequest.Clone();
810 operationDescription.Messages[1] = originalReply.Clone();
813 operationDescription.Messages[0] = originalRequest;
816 operationDescription.Messages[1] = originalReply;
820 internal virtual bool UseBareRequestFormatter(WebMessageBodyStyle style, OperationDescription operationDescription, out Type parameterType)
822 parameterType = null;
823 return IsBareRequest(style) && TryGetNonMessageParameterType(operationDescription.Messages[0], operationDescription, true, out parameterType);
826 static Collection<MessagePartDescription> CloneParts(MessageDescription md)
828 MessagePartDescriptionCollection bodyParameters = md.Body.Parts;
829 Collection<MessagePartDescription> bodyParametersClone = new Collection<MessagePartDescription>();
830 for (int i = 0; i < bodyParameters.Count; ++i)
832 MessagePartDescription copy = bodyParameters[i].Clone();
833 bodyParametersClone.Add(copy);
835 return bodyParametersClone;
838 static void EnsureNotUntypedMessageNorMessageContract(OperationDescription operationDescription)
840 // Called when there are UriTemplate parameters. UT does not compose with Message
841 // or MessageContract because the SOAP and REST programming models must be uniform here.
842 bool isUnadornedWebGet = false;
843 if (GetWebMethod(operationDescription) == GET && GetWebUriTemplate(operationDescription) == null)
845 isUnadornedWebGet = true;
847 if (IsTypedMessage(operationDescription.Messages[0]))
849 if (isUnadornedWebGet)
851 // WebGet will give you UriTemplate parameters by default.
852 // We need a special error message for this case to prevent confusion.
853 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
854 SR2.GetString(SR2.GETCannotHaveMCParameter, operationDescription.Name, operationDescription.DeclaringContract.Name, operationDescription.Messages[0].MessageType.Name)));
858 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR2.GetString(
859 SR2.UTParamsDoNotComposeWithMessageContract, operationDescription.Name, operationDescription.DeclaringContract.Name)));
863 if (IsUntypedMessage(operationDescription.Messages[0]))
865 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR2.GetString(
866 SR2.UTParamsDoNotComposeWithMessage, operationDescription.Name, operationDescription.DeclaringContract.Name)));
870 static void EnsureOk(WebGetAttribute wga, WebInvokeAttribute wia, OperationDescription od)
872 if (wga != null && wia != null)
874 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
875 SR2.GetString(SR2.MultipleWebAttributes, od.Name, od.DeclaringContract.Name)));
879 static void HideReplyMessage(OperationDescription operationDescription, Effect effect)
881 MessageDescription temp = null;
882 if (operationDescription.Messages.Count > 1)
884 temp = operationDescription.Messages[1];
885 operationDescription.Messages[1] = MakeDummyMessageDescription(MessageDirection.Output);
888 if (operationDescription.Messages.Count > 1)
890 operationDescription.Messages[1] = temp;
894 static void HideRequestUriTemplateParameters(OperationDescription operationDescription, UriTemplateClientFormatter throwAway, Effect effect)
896 HideRequestUriTemplateParameters(operationDescription, throwAway.pathMapping, throwAway.queryMapping, effect);
899 internal static void HideRequestUriTemplateParameters(OperationDescription operationDescription, UriTemplateDispatchFormatter throwAway, Effect effect)
901 HideRequestUriTemplateParameters(operationDescription, throwAway.pathMapping, throwAway.queryMapping, effect);
904 static void HideRequestUriTemplateParameters(OperationDescription operationDescription, Dictionary<int, string> pathMapping, Dictionary<int, KeyValuePair<string, Type>> queryMapping, Effect effect)
906 // mutate description to hide UriTemplate parameters
907 Collection<MessagePartDescription> originalParts = CloneParts(operationDescription.Messages[0]);
908 Collection<MessagePartDescription> parts = CloneParts(operationDescription.Messages[0]);
909 operationDescription.Messages[0].Body.Parts.Clear();
911 for (int i = 0; i < parts.Count; ++i)
913 if (!pathMapping.ContainsKey(i) && !queryMapping.ContainsKey(i))
915 operationDescription.Messages[0].Body.Parts.Add(parts[i]);
916 parts[i].Index = newIndex++;
920 // unmutate description
921 operationDescription.Messages[0].Body.Parts.Clear();
922 for (int i = 0; i < originalParts.Count; ++i)
924 operationDescription.Messages[0].Body.Parts.Add(originalParts[i]);
928 static bool IsBareRequest(WebMessageBodyStyle style)
930 return (style == WebMessageBodyStyle.Bare || style == WebMessageBodyStyle.WrappedResponse);
933 static bool IsBareResponse(WebMessageBodyStyle style)
935 return (style == WebMessageBodyStyle.Bare || style == WebMessageBodyStyle.WrappedRequest);
938 internal static bool TryGetNonMessageParameterType(MessageDescription message, OperationDescription declaringOperation, bool isRequest, out Type type)
945 if (IsTypedMessage(message) || IsUntypedMessage(message))
951 if (message.Body.Parts.Count > 1)
953 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR2.GetString(SR2.AtMostOneRequestBodyParameterAllowedForUnwrappedMessages, declaringOperation.Name, declaringOperation.DeclaringContract.Name)));
955 if (message.Body.Parts.Count == 1 && message.Body.Parts[0].Type != typeof(void))
957 type = message.Body.Parts[0].Type;
963 if (message.Body.Parts.Count > 0)
965 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR2.GetString(SR2.OnlyReturnValueBodyParameterAllowedForUnwrappedMessages, declaringOperation.Name, declaringOperation.DeclaringContract.Name)));
967 if (message.Body.ReturnValue != null && message.Body.ReturnValue.Type != typeof(void))
969 type = message.Body.ReturnValue.Type;
975 static bool TryGetStreamParameterType(MessageDescription message, OperationDescription declaringOperation, bool isRequest, out Type type)
978 if (message == null || IsTypedMessage(message) || IsUntypedMessage(message))
984 bool hasStream = false;
985 for (int i = 0; i < message.Body.Parts.Count; ++i)
987 if (typeof(Stream) == message.Body.Parts[i].Type)
989 type = message.Body.Parts[i].Type;
995 if (hasStream && message.Body.Parts.Count > 1)
997 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR2.GetString(SR2.AtMostOneRequestBodyParameterAllowedForStream, declaringOperation.Name, declaringOperation.DeclaringContract.Name)));
1003 // validate that the stream is not an out or ref param
1004 for (int i = 0; i < message.Body.Parts.Count; ++i)
1006 if (typeof(Stream) == message.Body.Parts[i].Type)
1008 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR2.GetString(SR2.NoOutOrRefStreamParametersAllowed, message.Body.Parts[i].Name, declaringOperation.Name, declaringOperation.DeclaringContract.Name)));
1011 if (message.Body.ReturnValue != null && typeof(Stream) == message.Body.ReturnValue.Type)
1013 // validate that there are no out or ref params
1014 if (message.Body.Parts.Count > 0)
1016 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR2.GetString(SR2.NoOutOrRefParametersAllowedWithStreamResult, declaringOperation.Name, declaringOperation.DeclaringContract.Name)));
1018 type = message.Body.ReturnValue.Type;
1029 static void ValidateAtMostOneStreamParameter(OperationDescription operation, bool request)
1034 TryGetStreamParameterType(operation.Messages[0], operation, true, out dummy);
1038 if (operation.Messages.Count > 1)
1040 TryGetStreamParameterType(operation.Messages[1], operation, false, out dummy);
1045 string GetDefaultContentType(bool isStream, bool useJson, WebMessageEncodingBindingElement webEncoding)
1049 return defaultStreamContentType;
1053 return JsonMessageEncoderFactory.GetContentType(webEncoding);
1061 IDispatchMessageFormatter GetDefaultDispatchFormatter(OperationDescription od, bool useJson, bool isWrapped)
1063 DataContractSerializerOperationBehavior dcsob = od.Behaviors.Find<DataContractSerializerOperationBehavior>();
1068 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR2.GetString(SR2.JsonFormatRequiresDataContract, od.Name, od.DeclaringContract.Name, od.DeclaringContract.Namespace)));
1070 return CreateDataContractJsonSerializerOperationFormatter(od, dcsob, isWrapped);
1074 EndpointDispatcher dummyED = new EndpointDispatcher(new EndpointAddress("http://localhost/"), "name", "");
1075 DispatchRuntime dispatchRuntime = dummyED.DispatchRuntime;
1076 DispatchOperation dop = new DispatchOperation(dispatchRuntime, "dummyDispatch", "urn:dummy");
1077 dop.Formatter = null;
1081 (dcsob as IOperationBehavior).ApplyDispatchBehavior(od, dop);
1082 return dop.Formatter;
1084 XmlSerializerOperationBehavior xsob = od.Behaviors.Find<XmlSerializerOperationBehavior>();
1087 xsob = new XmlSerializerOperationBehavior(od, xsob.XmlSerializerFormatAttribute, this.reflector);
1088 (xsob as IOperationBehavior).ApplyDispatchBehavior(od, dop);
1089 return dop.Formatter;
1095 internal virtual DataContractJsonSerializerOperationFormatter CreateDataContractJsonSerializerOperationFormatter(OperationDescription od, DataContractSerializerOperationBehavior dcsob, bool isWrapped)
1097 return new DataContractJsonSerializerOperationFormatter(od, dcsob.MaxItemsInObjectGraph, dcsob.IgnoreExtensionDataObject, dcsob.DataContractSurrogate, isWrapped, false, JavascriptCallbackParameterName);
1100 IClientMessageFormatter GetDefaultXmlAndJsonClientFormatter(OperationDescription od, bool isWrapped)
1102 IClientMessageFormatter xmlFormatter = GetDefaultClientFormatter(od, false, isWrapped);
1103 if (!SupportsJsonFormat(od))
1105 return xmlFormatter;
1107 IClientMessageFormatter jsonFormatter = GetDefaultClientFormatter(od, true, isWrapped);
1108 Dictionary<WebContentFormat, IClientMessageFormatter> map = new Dictionary<WebContentFormat, IClientMessageFormatter>();
1109 map.Add(WebContentFormat.Xml, xmlFormatter);
1110 map.Add(WebContentFormat.Json, jsonFormatter);
1111 // In case there is no format property, the default formatter to use is XML
1112 return new DemultiplexingClientMessageFormatter(map, xmlFormatter);
1115 IDispatchMessageFormatter GetDefaultXmlAndJsonDispatchFormatter(OperationDescription od, bool isWrapped)
1117 IDispatchMessageFormatter xmlFormatter = GetDefaultDispatchFormatter(od, false, isWrapped);
1118 if (!SupportsJsonFormat(od))
1120 return xmlFormatter;
1122 IDispatchMessageFormatter jsonFormatter = GetDefaultDispatchFormatter(od, true, isWrapped);
1123 Dictionary<WebContentFormat, IDispatchMessageFormatter> map = new Dictionary<WebContentFormat, IDispatchMessageFormatter>();
1124 map.Add(WebContentFormat.Xml, xmlFormatter);
1125 map.Add(WebContentFormat.Json, jsonFormatter);
1126 return new DemultiplexingDispatchMessageFormatter(map, xmlFormatter);
1129 internal WebMessageFormat GetRequestFormat(OperationDescription od)
1131 WebGetAttribute wga = od.Behaviors.Find<WebGetAttribute>();
1132 WebInvokeAttribute wia = od.Behaviors.Find<WebInvokeAttribute>();
1133 EnsureOk(wga, wia, od);
1136 return wga.IsRequestFormatSetExplicitly ? wga.RequestFormat : this.DefaultOutgoingRequestFormat;
1138 else if (wia != null)
1140 return wia.IsRequestFormatSetExplicitly ? wia.RequestFormat : this.DefaultOutgoingRequestFormat;
1144 return this.DefaultOutgoingRequestFormat;
1148 internal WebMessageFormat GetResponseFormat(OperationDescription od)
1150 WebGetAttribute wga = od.Behaviors.Find<WebGetAttribute>();
1151 WebInvokeAttribute wia = od.Behaviors.Find<WebInvokeAttribute>();
1152 EnsureOk(wga, wia, od);
1155 return wga.IsResponseFormatSetExplicitly ? wga.ResponseFormat : this.DefaultOutgoingResponseFormat;
1157 else if (wia != null)
1159 return wia.IsResponseFormatSetExplicitly ? wia.ResponseFormat : this.DefaultOutgoingResponseFormat;
1163 return this.DefaultOutgoingResponseFormat;
1167 void ValidateBodyParameters(OperationDescription operation, bool request)
1169 string method = GetWebMethod(operation);
1172 ValidateGETHasNoBody(operation, method);
1174 // validate that if bare is chosen for request/response, then at most 1 parameter is possible
1175 ValidateBodyStyle(operation, request);
1176 // validate if the request or response body is a stream, no other body parameters
1178 ValidateAtMostOneStreamParameter(operation, request);
1181 void ValidateBodyStyle(OperationDescription operation, bool request)
1183 WebMessageBodyStyle style = GetBodyStyle(operation);
1185 if (request && IsBareRequest(style))
1187 TryGetNonMessageParameterType(operation.Messages[0], operation, true, out dummy);
1189 if (!request && operation.Messages.Count > 1 && IsBareResponse(style))
1191 TryGetNonMessageParameterType(operation.Messages[1], operation, false, out dummy);
1195 void ValidateGETHasNoBody(OperationDescription operation, string method)
1199 if (!IsUntypedMessage(operation.Messages[0]) && operation.Messages[0].Body.Parts.Count != 0)
1201 if (!IsTypedMessage(operation.Messages[0]))
1203 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
1204 SR2.GetString(SR2.GETCannotHaveBody, operation.Name, operation.DeclaringContract.Name, operation.Messages[0].Body.Parts[0].Name)));
1208 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
1209 SR2.GetString(SR2.GETCannotHaveMCParameter, operation.Name, operation.DeclaringContract.Name, operation.Messages[0].MessageType.Name)));
1215 void ValidateContract(ServiceEndpoint endpoint)
1217 foreach (OperationDescription od in endpoint.Contract.Operations)
1219 ValidateNoOperationHasEncodedXmlSerializer(od);
1220 ValidateNoMessageContractHeaders(od.Messages[0], od.Name, endpoint.Contract.Name);
1221 ValidateNoBareMessageContractWithMultipleParts(od.Messages[0], od.Name, endpoint.Contract.Name);
1222 ValidateNoMessageContractWithStream(od.Messages[0], od.Name, endpoint.Contract.Name);
1223 if (od.Messages.Count > 1)
1225 ValidateNoMessageContractHeaders(od.Messages[1], od.Name, endpoint.Contract.Name);
1226 ValidateNoBareMessageContractWithMultipleParts(od.Messages[1], od.Name, endpoint.Contract.Name);
1227 ValidateNoMessageContractWithStream(od.Messages[1], od.Name, endpoint.Contract.Name);
1232 internal static bool IsXmlSerializerFaultFormat(OperationDescription operationDescription)
1234 XmlSerializerOperationBehavior xsob = operationDescription.Behaviors.Find<XmlSerializerOperationBehavior>();
1235 return (xsob != null && xsob.XmlSerializerFormatAttribute.SupportFaults);
1238 void ValidateNoMessageContractWithStream(MessageDescription md, string opName, string contractName)
1240 if (IsTypedMessage(md))
1242 foreach (MessagePartDescription description in md.Body.Parts)
1244 if (description.Type == typeof(Stream))
1246 throw System.ServiceModel.DiagnosticUtility.ExceptionUtility.ThrowHelperError(
1247 new InvalidOperationException(System.ServiceModel.SR2.GetString(System.ServiceModel.SR2.StreamBodyMemberNotSupported, this.GetType().ToString(), contractName, opName, md.MessageType.ToString(), description.Name)));
1253 void ValidateNoOperationHasEncodedXmlSerializer(OperationDescription od)
1255 XmlSerializerOperationBehavior xsob = od.Behaviors.Find<XmlSerializerOperationBehavior>();
1256 if (xsob != null && (xsob.XmlSerializerFormatAttribute.Style == OperationFormatStyle.Rpc || xsob.XmlSerializerFormatAttribute.IsEncoded))
1258 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR2.GetString(SR2.RpcEncodedNotSupportedForNoneMessageVersion, od.Name, od.DeclaringContract.Name, od.DeclaringContract.Namespace)));
1262 void ValidateNoBareMessageContractWithMultipleParts(MessageDescription md, string opName, string contractName)
1264 if (IsTypedMessage(md) && md.Body.WrapperName == null)
1266 if (md.Body.Parts.Count > 1)
1268 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
1269 SR2.GetString(SR2.InvalidMessageContractWithoutWrapperName, opName, contractName, md.MessageType)));
1271 if (md.Body.Parts.Count == 1 && md.Body.Parts[0].Multiple)
1273 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR2.GetString(SR2.MCAtMostOneRequestBodyParameterAllowedForUnwrappedMessages, opName, contractName, md.MessageType)));
1278 void ValidateNoMessageContractHeaders(MessageDescription md, string opName, string contractName)
1280 if (md.Headers.Count != 0)
1282 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
1283 SR2.GetString(SR2.InvalidMethodWithSOAPHeaders, opName, contractName)));
1287 internal class MessagePassthroughFormatter : IClientMessageFormatter, IDispatchMessageFormatter
1289 public object DeserializeReply(Message message, object[] parameters)
1294 public void DeserializeRequest(Message message, object[] parameters)
1296 parameters[0] = message;
1299 public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result)
1301 return result as Message;
1304 public Message SerializeRequest(MessageVersion messageVersion, object[] parameters)
1306 return parameters[0] as Message;
1310 static internal JavascriptCallbackResponseMessageProperty TrySetupJavascriptCallback(string callbackParameterName)
1312 JavascriptCallbackResponseMessageProperty javascriptProperty = null;
1313 if (!String.IsNullOrEmpty(callbackParameterName) &&
1314 !OperationContext.Current.OutgoingMessageProperties.TryGetValue<JavascriptCallbackResponseMessageProperty>(JavascriptCallbackResponseMessageProperty.Name, out javascriptProperty))
1316 UriTemplateMatch match = WebOperationContext.Current.IncomingRequest.UriTemplateMatch;
1317 if (match != null &&
1318 match.QueryParameters.AllKeys.Contains(callbackParameterName))
1320 string callbackName = match.QueryParameters[callbackParameterName];
1322 if (!String.IsNullOrEmpty(callbackName))
1324 javascriptProperty = new JavascriptCallbackResponseMessageProperty
1326 CallbackFunctionName = callbackName
1328 OperationContext.Current.OutgoingMessageProperties.Add(JavascriptCallbackResponseMessageProperty.Name, javascriptProperty);
1332 return javascriptProperty;