[bcl] Updates referencesource to 4.7.1
[mono-project.git] / mcs / class / referencesource / System.ServiceModel.Web / System / ServiceModel / Description / WebHttpBehavior.cs
blob7538ece4fa61f1840320ef0ad8feb1cdbb267cd6
1 //------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 //------------------------------------------------------------
4 #pragma warning disable 1634, 1691
5 namespace System.ServiceModel.Description
7 using System;
8 using System.Collections.Generic;
9 using System.Collections.ObjectModel;
10 using System.ComponentModel;
11 using System.IO;
12 using System.Linq;
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; }
47 set
49 if (!WebMessageBodyStyleHelper.IsDefined(value))
51 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value"));
53 this.defaultBodyStyle = value;
57 public virtual WebMessageFormat DefaultOutgoingRequestFormat
59 get
61 return this.defaultOutgoingRequestFormat;
63 set
65 if (!WebMessageFormatHelper.IsDefined(value))
67 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value"));
69 this.defaultOutgoingRequestFormat = value;
73 public virtual WebMessageFormat DefaultOutgoingResponseFormat
75 get
77 return this.defaultOutgoingReplyFormat;
79 set
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)
101 // do nothing
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;
162 else
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
176 // endpoint filter
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;
193 break;
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);
225 else
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
254 if (dop != null)
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());
303 return result;
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)
344 return;
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);
363 if (wga != null)
365 return GET;
367 else if (wia != null)
369 return wia.Method ?? POST;
371 else
373 return 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);
383 if (wga != null)
385 return wga.UriTemplate;
387 else if (wia != null)
389 return wia.UriTemplate;
391 else
393 return null;
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);
408 else if (od.TaskMethod != null)
410 attributes = od.TaskMethod.GetCustomAttributes(typeof(DescriptionAttribute), true);
413 if (attributes != null && attributes.Length > 0)
415 return ((DescriptionAttribute)attributes[0]).Description;
417 else
419 return String.Empty;
423 internal static bool IsTypedMessage(MessageDescription message)
425 return (message != null && message.MessageType != null);
428 internal static bool IsUntypedMessage(MessageDescription message)
430 if (message == null)
432 return false;
434 return (message.Body.ReturnValue != null && message.Body.Parts.Count == 0 && message.Body.ReturnValue.Type == typeof(Message)) ||
435 (message.Body.ReturnValue == null && message.Body.Parts.Count == 1 && message.Body.Parts[0].Type == typeof(Message));
438 internal static MessageDescription MakeDummyMessageDescription(MessageDirection direction)
440 MessageDescription messageDescription = new MessageDescription("urn:dummyAction", direction);
441 return messageDescription;
444 internal static bool SupportsJsonFormat(OperationDescription od)
446 // if the type is XmlSerializable, then we cannot create a json serializer for it
447 DataContractSerializerOperationBehavior dcsob = od.Behaviors.Find<DataContractSerializerOperationBehavior>();
448 return (dcsob != null);
451 internal static void ValidateIsWebHttpBinding(ServiceEndpoint serviceEndpoint, string behaviorName)
453 Binding binding = serviceEndpoint.Binding;
454 if (binding.Scheme != "http" && binding.Scheme != "https")
456 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
457 SR2.GetString(SR2.WCFBindingCannotBeUsedWithUriOperationSelectorBehaviorBadScheme,
458 serviceEndpoint.Contract.Name, behaviorName)));
460 if (binding.MessageVersion != MessageVersion.None)
462 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
463 SR2.GetString(SR2.WCFBindingCannotBeUsedWithUriOperationSelectorBehaviorBadMessageVersion,
464 serviceEndpoint.Address.Uri.AbsoluteUri, behaviorName)));
466 TransportBindingElement transportBindingElement = binding.CreateBindingElements().Find<TransportBindingElement>();
467 if (transportBindingElement != null && !transportBindingElement.ManualAddressing)
469 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
470 SR2.GetString(SR2.ManualAddressingCannotBeFalseWithTransportBindingElement,
471 serviceEndpoint.Address.Uri.AbsoluteUri, behaviorName, transportBindingElement.GetType().Name)));
475 internal WebMessageBodyStyle GetBodyStyle(OperationDescription od)
477 WebGetAttribute wga = od.Behaviors.Find<WebGetAttribute>();
478 WebInvokeAttribute wia = od.Behaviors.Find<WebInvokeAttribute>();
479 EnsureOk(wga, wia, od);
480 if (wga != null)
482 return wga.GetBodyStyleOrDefault(this.DefaultBodyStyle);
484 else if (wia != null)
486 return wia.GetBodyStyleOrDefault(this.DefaultBodyStyle);
488 else
490 return this.DefaultBodyStyle;
494 internal IClientMessageFormatter GetDefaultClientFormatter(OperationDescription od, bool useJson, bool isWrapped)
496 DataContractSerializerOperationBehavior dcsob = od.Behaviors.Find<DataContractSerializerOperationBehavior>();
497 if (useJson)
499 if (dcsob == null)
501 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR2.GetString(SR2.JsonFormatRequiresDataContract, od.Name, od.DeclaringContract.Name, od.DeclaringContract.Namespace)));
503 return CreateDataContractJsonSerializerOperationFormatter(od, dcsob, isWrapped);
505 else
507 ClientRuntime clientRuntime = new ClientRuntime("name", "");
508 ClientOperation cop = new ClientOperation(clientRuntime, "dummyClient", "urn:dummy");
509 cop.Formatter = null;
511 if (dcsob != null)
513 (dcsob as IOperationBehavior).ApplyClientBehavior(od, cop);
514 return cop.Formatter;
516 XmlSerializerOperationBehavior xsob = od.Behaviors.Find<XmlSerializerOperationBehavior>();
517 if (xsob != null)
519 xsob = new XmlSerializerOperationBehavior(od, xsob.XmlSerializerFormatAttribute, this.reflector);
520 (xsob as IOperationBehavior).ApplyClientBehavior(od, cop);
521 return cop.Formatter;
524 return null;
527 protected virtual void AddClientErrorInspector(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
529 if (!this.FaultExceptionEnabled)
531 clientRuntime.MessageInspectors.Add(new WebFaultClientMessageInspector());
533 else
535 clientRuntime.MessageVersionNoneFaultsEnabled = true;
539 protected virtual void AddServerErrorHandlers(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
541 if (!this.FaultExceptionEnabled)
543 WebErrorHandler errorHandler = new WebErrorHandler(this, endpoint.Contract, endpointDispatcher.DispatchRuntime.ChannelDispatcher.IncludeExceptionDetailInFaults);
544 endpointDispatcher.DispatchRuntime.ChannelDispatcher.ErrorHandlers.Add(errorHandler);
548 protected virtual WebHttpDispatchOperationSelector GetOperationSelector(ServiceEndpoint endpoint)
550 return new WebHttpDispatchOperationSelector(endpoint);
553 protected virtual QueryStringConverter GetQueryStringConverter(OperationDescription operationDescription)
555 return new QueryStringConverter();
558 protected virtual IClientMessageFormatter GetReplyClientFormatter(OperationDescription operationDescription, ServiceEndpoint endpoint)
560 if (operationDescription.Messages.Count < 2)
562 return null;
564 ValidateBodyParameters(operationDescription, false);
565 Type type;
566 if (TryGetStreamParameterType(operationDescription.Messages[1], operationDescription, false, out type))
568 return new HttpStreamFormatter(operationDescription);
570 if (IsUntypedMessage(operationDescription.Messages[1]))
572 return new MessagePassthroughFormatter();
574 WebMessageBodyStyle style = GetBodyStyle(operationDescription);
575 Type parameterType;
576 if (UseBareReplyFormatter(style, operationDescription, GetResponseFormat(operationDescription), out parameterType))
578 return SingleBodyParameterMessageFormatter.CreateXmlAndJsonClientFormatter(operationDescription, parameterType, false, this.xmlSerializerManager);
580 else
582 MessageDescription temp = operationDescription.Messages[0];
583 operationDescription.Messages[0] = MakeDummyMessageDescription(MessageDirection.Input);
584 IClientMessageFormatter result;
585 result = GetDefaultXmlAndJsonClientFormatter(operationDescription, !IsBareResponse(style));
586 operationDescription.Messages[0] = temp;
587 return result;
591 internal virtual bool UseBareReplyFormatter(WebMessageBodyStyle style, OperationDescription operationDescription, WebMessageFormat responseFormat, out Type parameterType)
593 parameterType = null;
594 return IsBareResponse(style) && TryGetNonMessageParameterType(operationDescription.Messages[1], operationDescription, false, out parameterType);
597 protected virtual IDispatchMessageFormatter GetReplyDispatchFormatter(OperationDescription operationDescription, ServiceEndpoint endpoint)
599 if (operationDescription.Messages.Count < 2)
601 return null;
603 ValidateBodyParameters(operationDescription, false);
604 WebMessageFormat responseFormat = GetResponseFormat(operationDescription);
606 // Determine if we should add a json formatter; If the ResponseFormat is json, we always add the json formatter even if the
607 // operation is XmlSerializerFormat because the formatter constructor throws the exception: "json not valid with XmlSerializerFormat" [Microsoft]
608 bool useJson = (responseFormat == WebMessageFormat.Json || SupportsJsonFormat(operationDescription));
610 IDispatchMessageFormatter innerFormatter;
611 Type type;
613 if (TryGetStreamParameterType(operationDescription.Messages[1], operationDescription, false, out type))
615 innerFormatter = new ContentTypeSettingDispatchMessageFormatter(defaultStreamContentType, new HttpStreamFormatter(operationDescription));
617 else if (IsUntypedMessage(operationDescription.Messages[1]))
619 innerFormatter = new MessagePassthroughFormatter();
621 else
623 Type parameterType;
624 WebMessageBodyStyle style = GetBodyStyle(operationDescription);
625 Dictionary<WebMessageFormat, IDispatchMessageFormatter> formatters = new Dictionary<WebMessageFormat, IDispatchMessageFormatter>();
627 if (UseBareReplyFormatter(style, operationDescription, responseFormat, out parameterType))
629 formatters.Add(WebMessageFormat.Xml, SingleBodyParameterMessageFormatter.CreateDispatchFormatter(operationDescription, parameterType, false, false, this.xmlSerializerManager, null));
630 if (useJson)
632 formatters.Add(WebMessageFormat.Json, SingleBodyParameterMessageFormatter.CreateDispatchFormatter(operationDescription, parameterType, false, true, this.xmlSerializerManager, this.JavascriptCallbackParameterName));
635 else
637 MessageDescription temp = operationDescription.Messages[0];
638 operationDescription.Messages[0] = MakeDummyMessageDescription(MessageDirection.Input);
639 formatters.Add(WebMessageFormat.Xml, GetDefaultDispatchFormatter(operationDescription, false, !IsBareResponse(style)));
640 if (useJson)
642 formatters.Add(WebMessageFormat.Json, GetDefaultDispatchFormatter(operationDescription, true, !IsBareResponse(style)));
644 operationDescription.Messages[0] = temp;
646 innerFormatter = new MultiplexingDispatchMessageFormatter(formatters, responseFormat);
649 return innerFormatter;
652 protected virtual IClientMessageFormatter GetRequestClientFormatter(OperationDescription operationDescription, ServiceEndpoint endpoint)
654 WebMessageFormat requestFormat = GetRequestFormat(operationDescription);
655 bool useJson = (requestFormat == WebMessageFormat.Json);
656 WebMessageEncodingBindingElement webEncoding = (useJson) ? endpoint.Binding.CreateBindingElements().Find<WebMessageEncodingBindingElement>() : null;
657 IClientMessageFormatter innerFormatter = null;
659 // get some validation errors by creating "throwAway" formatter
661 // validate that endpoint.Address is not null before accessing the endpoint.Address.Uri. This is to avoid throwing a NullRefException while constructing a UriTemplateClientFormatter
662 if (endpoint.Address == null)
664 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
665 SR2.GetString(SR2.ServiceEndpointMustHaveNonNullAddress, typeof(ServiceEndpoint), typeof(ChannelFactory), typeof(WebHttpEndpoint), AddressPropertyName, typeof(ServiceEndpoint))));
668 UriTemplateClientFormatter throwAway = new UriTemplateClientFormatter(operationDescription, null, GetQueryStringConverter(operationDescription), endpoint.Address.Uri, false, endpoint.Contract.Name);
669 int numUriVariables = throwAway.pathMapping.Count + throwAway.queryMapping.Count;
670 bool isStream = false;
671 HideReplyMessage(operationDescription, delegate()
673 WebMessageBodyStyle style = GetBodyStyle(operationDescription);
674 bool isUntypedWhenUriParamsNotConsidered = false;
675 Effect doBodyFormatter = delegate()
677 if (numUriVariables != 0)
679 EnsureNotUntypedMessageNorMessageContract(operationDescription);
681 // get body formatter
682 ValidateBodyParameters(operationDescription, true);
683 IClientMessageFormatter baseFormatter;
684 Type parameterType;
685 if (TryGetStreamParameterType(operationDescription.Messages[0], operationDescription, true, out parameterType))
687 isStream = true;
688 baseFormatter = new HttpStreamFormatter(operationDescription);
690 else if (UseBareRequestFormatter(style, operationDescription, out parameterType))
692 baseFormatter = SingleBodyParameterMessageFormatter.CreateClientFormatter(operationDescription, parameterType, true, useJson, this.xmlSerializerManager);
694 else
696 baseFormatter = GetDefaultClientFormatter(operationDescription, useJson, !IsBareRequest(style));
698 innerFormatter = baseFormatter;
699 isUntypedWhenUriParamsNotConsidered = IsUntypedMessage(operationDescription.Messages[0]);
701 if (numUriVariables == 0)
703 if (IsUntypedMessage(operationDescription.Messages[0]))
705 ValidateBodyParameters(operationDescription, true);
706 innerFormatter = new MessagePassthroughFormatter();
707 isUntypedWhenUriParamsNotConsidered = true;
709 else if (IsTypedMessage(operationDescription.Messages[0]))
711 ValidateBodyParameters(operationDescription, true);
712 innerFormatter = GetDefaultClientFormatter(operationDescription, useJson, !IsBareRequest(style));
714 else
716 doBodyFormatter();
719 else
721 HideRequestUriTemplateParameters(operationDescription, throwAway, delegate()
723 CloneMessageDescriptionsBeforeActing(operationDescription, delegate()
725 doBodyFormatter();
729 innerFormatter = new UriTemplateClientFormatter(operationDescription, innerFormatter, GetQueryStringConverter(operationDescription), endpoint.Address.Uri, isUntypedWhenUriParamsNotConsidered, endpoint.Contract.Name);
731 string defaultContentType = GetDefaultContentType(isStream, useJson, webEncoding);
732 if (!string.IsNullOrEmpty(defaultContentType))
734 innerFormatter = new ContentTypeSettingClientMessageFormatter(defaultContentType, innerFormatter);
736 return innerFormatter;
739 protected virtual IDispatchMessageFormatter GetRequestDispatchFormatter(OperationDescription operationDescription, ServiceEndpoint endpoint)
741 IDispatchMessageFormatter result = null;
742 // get some validation errors by creating "throwAway" formatter
743 UriTemplateDispatchFormatter throwAway = new UriTemplateDispatchFormatter(operationDescription, null, GetQueryStringConverter(operationDescription), endpoint.Contract.Name, endpoint.Address.Uri);
744 int numUriVariables = throwAway.pathMapping.Count + throwAway.queryMapping.Count;
745 HideReplyMessage(operationDescription, delegate()
747 WebMessageBodyStyle style = GetBodyStyle(operationDescription);
748 Effect doBodyFormatter = delegate()
750 if (numUriVariables != 0)
752 EnsureNotUntypedMessageNorMessageContract(operationDescription);
754 // get body formatter
755 ValidateBodyParameters(operationDescription, true);
756 Type type;
757 if (TryGetStreamParameterType(operationDescription.Messages[0], operationDescription, true, out type))
759 result = new HttpStreamFormatter(operationDescription);
761 else
763 Type parameterType;
764 if (UseBareRequestFormatter(style, operationDescription, out parameterType))
766 result = SingleBodyParameterMessageFormatter.CreateXmlAndJsonDispatchFormatter(operationDescription, parameterType, true, this.xmlSerializerManager, this.JavascriptCallbackParameterName);
768 else
770 result = GetDefaultXmlAndJsonDispatchFormatter(operationDescription, !IsBareRequest(style));
774 if (numUriVariables == 0)
776 if (IsUntypedMessage(operationDescription.Messages[0]))
778 ValidateBodyParameters(operationDescription, true);
779 result = new MessagePassthroughFormatter();
781 else if (IsTypedMessage(operationDescription.Messages[0]))
783 ValidateBodyParameters(operationDescription, true);
784 result = GetDefaultXmlAndJsonDispatchFormatter(operationDescription, !IsBareRequest(style));
786 else
788 doBodyFormatter();
791 else
793 HideRequestUriTemplateParameters(operationDescription, throwAway, delegate()
795 CloneMessageDescriptionsBeforeActing(operationDescription, delegate()
797 doBodyFormatter();
801 result = new UriTemplateDispatchFormatter(operationDescription, result, GetQueryStringConverter(operationDescription), endpoint.Contract.Name, endpoint.Address.Uri);
803 return result;
806 static void CloneMessageDescriptionsBeforeActing(OperationDescription operationDescription, Effect effect)
808 MessageDescription originalRequest = operationDescription.Messages[0];
809 bool thereIsAReply = operationDescription.Messages.Count > 1;
810 MessageDescription originalReply = thereIsAReply ? operationDescription.Messages[1] : null;
811 operationDescription.Messages[0] = originalRequest.Clone();
812 if (thereIsAReply)
814 operationDescription.Messages[1] = originalReply.Clone();
816 effect();
817 operationDescription.Messages[0] = originalRequest;
818 if (thereIsAReply)
820 operationDescription.Messages[1] = originalReply;
824 internal virtual bool UseBareRequestFormatter(WebMessageBodyStyle style, OperationDescription operationDescription, out Type parameterType)
826 parameterType = null;
827 return IsBareRequest(style) && TryGetNonMessageParameterType(operationDescription.Messages[0], operationDescription, true, out parameterType);
830 static Collection<MessagePartDescription> CloneParts(MessageDescription md)
832 MessagePartDescriptionCollection bodyParameters = md.Body.Parts;
833 Collection<MessagePartDescription> bodyParametersClone = new Collection<MessagePartDescription>();
834 for (int i = 0; i < bodyParameters.Count; ++i)
836 MessagePartDescription copy = bodyParameters[i].Clone();
837 bodyParametersClone.Add(copy);
839 return bodyParametersClone;
842 static void EnsureNotUntypedMessageNorMessageContract(OperationDescription operationDescription)
844 // Called when there are UriTemplate parameters. UT does not compose with Message
845 // or MessageContract because the SOAP and REST programming models must be uniform here.
846 bool isUnadornedWebGet = false;
847 if (GetWebMethod(operationDescription) == GET && GetWebUriTemplate(operationDescription) == null)
849 isUnadornedWebGet = true;
851 if (IsTypedMessage(operationDescription.Messages[0]))
853 if (isUnadornedWebGet)
855 // WebGet will give you UriTemplate parameters by default.
856 // We need a special error message for this case to prevent confusion.
857 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
858 SR2.GetString(SR2.GETCannotHaveMCParameter, operationDescription.Name, operationDescription.DeclaringContract.Name, operationDescription.Messages[0].MessageType.Name)));
860 else
862 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR2.GetString(
863 SR2.UTParamsDoNotComposeWithMessageContract, operationDescription.Name, operationDescription.DeclaringContract.Name)));
867 if (IsUntypedMessage(operationDescription.Messages[0]))
869 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR2.GetString(
870 SR2.UTParamsDoNotComposeWithMessage, operationDescription.Name, operationDescription.DeclaringContract.Name)));
874 static void EnsureOk(WebGetAttribute wga, WebInvokeAttribute wia, OperationDescription od)
876 if (wga != null && wia != null)
878 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
879 SR2.GetString(SR2.MultipleWebAttributes, od.Name, od.DeclaringContract.Name)));
883 static void HideReplyMessage(OperationDescription operationDescription, Effect effect)
885 MessageDescription temp = null;
886 if (operationDescription.Messages.Count > 1)
888 temp = operationDescription.Messages[1];
889 operationDescription.Messages[1] = MakeDummyMessageDescription(MessageDirection.Output);
891 effect();
892 if (operationDescription.Messages.Count > 1)
894 operationDescription.Messages[1] = temp;
898 static void HideRequestUriTemplateParameters(OperationDescription operationDescription, UriTemplateClientFormatter throwAway, Effect effect)
900 HideRequestUriTemplateParameters(operationDescription, throwAway.pathMapping, throwAway.queryMapping, effect);
903 internal static void HideRequestUriTemplateParameters(OperationDescription operationDescription, UriTemplateDispatchFormatter throwAway, Effect effect)
905 HideRequestUriTemplateParameters(operationDescription, throwAway.pathMapping, throwAway.queryMapping, effect);
908 static void HideRequestUriTemplateParameters(OperationDescription operationDescription, Dictionary<int, string> pathMapping, Dictionary<int, KeyValuePair<string, Type>> queryMapping, Effect effect)
910 // mutate description to hide UriTemplate parameters
911 Collection<MessagePartDescription> originalParts = CloneParts(operationDescription.Messages[0]);
912 Collection<MessagePartDescription> parts = CloneParts(operationDescription.Messages[0]);
913 operationDescription.Messages[0].Body.Parts.Clear();
914 int newIndex = 0;
915 for (int i = 0; i < parts.Count; ++i)
917 if (!pathMapping.ContainsKey(i) && !queryMapping.ContainsKey(i))
919 operationDescription.Messages[0].Body.Parts.Add(parts[i]);
920 parts[i].Index = newIndex++;
923 effect();
924 // unmutate description
925 operationDescription.Messages[0].Body.Parts.Clear();
926 for (int i = 0; i < originalParts.Count; ++i)
928 operationDescription.Messages[0].Body.Parts.Add(originalParts[i]);
932 static bool IsBareRequest(WebMessageBodyStyle style)
934 return (style == WebMessageBodyStyle.Bare || style == WebMessageBodyStyle.WrappedResponse);
937 static bool IsBareResponse(WebMessageBodyStyle style)
939 return (style == WebMessageBodyStyle.Bare || style == WebMessageBodyStyle.WrappedRequest);
942 internal static bool TryGetNonMessageParameterType(MessageDescription message, OperationDescription declaringOperation, bool isRequest, out Type type)
944 type = null;
945 if (message == null)
947 return true;
949 if (IsTypedMessage(message) || IsUntypedMessage(message))
951 return false;
953 if (isRequest)
955 if (message.Body.Parts.Count > 1)
957 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR2.GetString(SR2.AtMostOneRequestBodyParameterAllowedForUnwrappedMessages, declaringOperation.Name, declaringOperation.DeclaringContract.Name)));
959 if (message.Body.Parts.Count == 1 && message.Body.Parts[0].Type != typeof(void))
961 type = message.Body.Parts[0].Type;
963 return true;
965 else
967 if (message.Body.Parts.Count > 0)
969 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR2.GetString(SR2.OnlyReturnValueBodyParameterAllowedForUnwrappedMessages, declaringOperation.Name, declaringOperation.DeclaringContract.Name)));
971 if (message.Body.ReturnValue != null && message.Body.ReturnValue.Type != typeof(void))
973 type = message.Body.ReturnValue.Type;
975 return true;
979 static bool TryGetStreamParameterType(MessageDescription message, OperationDescription declaringOperation, bool isRequest, out Type type)
981 type = null;
982 if (message == null || IsTypedMessage(message) || IsUntypedMessage(message))
984 return false;
986 if (isRequest)
988 bool hasStream = false;
989 for (int i = 0; i < message.Body.Parts.Count; ++i)
991 if (typeof(Stream) == message.Body.Parts[i].Type)
993 type = message.Body.Parts[i].Type;
994 hasStream = true;
995 break;
999 if (hasStream && message.Body.Parts.Count > 1)
1001 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR2.GetString(SR2.AtMostOneRequestBodyParameterAllowedForStream, declaringOperation.Name, declaringOperation.DeclaringContract.Name)));
1003 return hasStream;
1005 else
1007 // validate that the stream is not an out or ref param
1008 for (int i = 0; i < message.Body.Parts.Count; ++i)
1010 if (typeof(Stream) == message.Body.Parts[i].Type)
1012 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR2.GetString(SR2.NoOutOrRefStreamParametersAllowed, message.Body.Parts[i].Name, declaringOperation.Name, declaringOperation.DeclaringContract.Name)));
1015 if (message.Body.ReturnValue != null && typeof(Stream) == message.Body.ReturnValue.Type)
1017 // validate that there are no out or ref params
1018 if (message.Body.Parts.Count > 0)
1020 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR2.GetString(SR2.NoOutOrRefParametersAllowedWithStreamResult, declaringOperation.Name, declaringOperation.DeclaringContract.Name)));
1022 type = message.Body.ReturnValue.Type;
1023 return true;
1026 else
1028 return false;
1033 static void ValidateAtMostOneStreamParameter(OperationDescription operation, bool request)
1035 Type dummy;
1036 if (request)
1038 TryGetStreamParameterType(operation.Messages[0], operation, true, out dummy);
1040 else
1042 if (operation.Messages.Count > 1)
1044 TryGetStreamParameterType(operation.Messages[1], operation, false, out dummy);
1049 string GetDefaultContentType(bool isStream, bool useJson, WebMessageEncodingBindingElement webEncoding)
1051 if (isStream)
1053 return defaultStreamContentType;
1055 else if (useJson)
1057 return JsonMessageEncoderFactory.GetContentType(webEncoding);
1059 else
1061 return null;
1065 IDispatchMessageFormatter GetDefaultDispatchFormatter(OperationDescription od, bool useJson, bool isWrapped)
1067 DataContractSerializerOperationBehavior dcsob = od.Behaviors.Find<DataContractSerializerOperationBehavior>();
1068 if (useJson)
1070 if (dcsob == null)
1072 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR2.GetString(SR2.JsonFormatRequiresDataContract, od.Name, od.DeclaringContract.Name, od.DeclaringContract.Namespace)));
1074 return CreateDataContractJsonSerializerOperationFormatter(od, dcsob, isWrapped);
1076 else
1078 EndpointDispatcher dummyED = new EndpointDispatcher(new EndpointAddress("http://localhost/"), "name", "");
1079 DispatchRuntime dispatchRuntime = dummyED.DispatchRuntime;
1080 DispatchOperation dop = new DispatchOperation(dispatchRuntime, "dummyDispatch", "urn:dummy");
1081 dop.Formatter = null;
1083 if (dcsob != null)
1085 (dcsob as IOperationBehavior).ApplyDispatchBehavior(od, dop);
1086 return dop.Formatter;
1088 XmlSerializerOperationBehavior xsob = od.Behaviors.Find<XmlSerializerOperationBehavior>();
1089 if (xsob != null)
1091 xsob = new XmlSerializerOperationBehavior(od, xsob.XmlSerializerFormatAttribute, this.reflector);
1092 (xsob as IOperationBehavior).ApplyDispatchBehavior(od, dop);
1093 return dop.Formatter;
1096 return null;
1099 internal virtual DataContractJsonSerializerOperationFormatter CreateDataContractJsonSerializerOperationFormatter(OperationDescription od, DataContractSerializerOperationBehavior dcsob, bool isWrapped)
1101 return new DataContractJsonSerializerOperationFormatter(od, dcsob.MaxItemsInObjectGraph, dcsob.IgnoreExtensionDataObject, dcsob.DataContractSurrogate, isWrapped, false, JavascriptCallbackParameterName);
1104 IClientMessageFormatter GetDefaultXmlAndJsonClientFormatter(OperationDescription od, bool isWrapped)
1106 IClientMessageFormatter xmlFormatter = GetDefaultClientFormatter(od, false, isWrapped);
1107 if (!SupportsJsonFormat(od))
1109 return xmlFormatter;
1111 IClientMessageFormatter jsonFormatter = GetDefaultClientFormatter(od, true, isWrapped);
1112 Dictionary<WebContentFormat, IClientMessageFormatter> map = new Dictionary<WebContentFormat, IClientMessageFormatter>();
1113 map.Add(WebContentFormat.Xml, xmlFormatter);
1114 map.Add(WebContentFormat.Json, jsonFormatter);
1115 // In case there is no format property, the default formatter to use is XML
1116 return new DemultiplexingClientMessageFormatter(map, xmlFormatter);
1119 IDispatchMessageFormatter GetDefaultXmlAndJsonDispatchFormatter(OperationDescription od, bool isWrapped)
1121 IDispatchMessageFormatter xmlFormatter = GetDefaultDispatchFormatter(od, false, isWrapped);
1122 if (!SupportsJsonFormat(od))
1124 return xmlFormatter;
1126 IDispatchMessageFormatter jsonFormatter = GetDefaultDispatchFormatter(od, true, isWrapped);
1127 Dictionary<WebContentFormat, IDispatchMessageFormatter> map = new Dictionary<WebContentFormat, IDispatchMessageFormatter>();
1128 map.Add(WebContentFormat.Xml, xmlFormatter);
1129 map.Add(WebContentFormat.Json, jsonFormatter);
1130 return new DemultiplexingDispatchMessageFormatter(map, xmlFormatter);
1133 internal WebMessageFormat GetRequestFormat(OperationDescription od)
1135 WebGetAttribute wga = od.Behaviors.Find<WebGetAttribute>();
1136 WebInvokeAttribute wia = od.Behaviors.Find<WebInvokeAttribute>();
1137 EnsureOk(wga, wia, od);
1138 if (wga != null)
1140 return wga.IsRequestFormatSetExplicitly ? wga.RequestFormat : this.DefaultOutgoingRequestFormat;
1142 else if (wia != null)
1144 return wia.IsRequestFormatSetExplicitly ? wia.RequestFormat : this.DefaultOutgoingRequestFormat;
1146 else
1148 return this.DefaultOutgoingRequestFormat;
1152 internal WebMessageFormat GetResponseFormat(OperationDescription od)
1154 WebGetAttribute wga = od.Behaviors.Find<WebGetAttribute>();
1155 WebInvokeAttribute wia = od.Behaviors.Find<WebInvokeAttribute>();
1156 EnsureOk(wga, wia, od);
1157 if (wga != null)
1159 return wga.IsResponseFormatSetExplicitly ? wga.ResponseFormat : this.DefaultOutgoingResponseFormat;
1161 else if (wia != null)
1163 return wia.IsResponseFormatSetExplicitly ? wia.ResponseFormat : this.DefaultOutgoingResponseFormat;
1165 else
1167 return this.DefaultOutgoingResponseFormat;
1171 void ValidateBodyParameters(OperationDescription operation, bool request)
1173 string method = GetWebMethod(operation);
1174 if (request)
1176 ValidateGETHasNoBody(operation, method);
1178 // validate that if bare is chosen for request/response, then at most 1 parameter is possible
1179 ValidateBodyStyle(operation, request);
1180 // validate if the request or response body is a stream, no other body parameters
1181 // can be specified
1182 ValidateAtMostOneStreamParameter(operation, request);
1185 void ValidateBodyStyle(OperationDescription operation, bool request)
1187 WebMessageBodyStyle style = GetBodyStyle(operation);
1188 Type dummy;
1189 if (request && IsBareRequest(style))
1191 TryGetNonMessageParameterType(operation.Messages[0], operation, true, out dummy);
1193 if (!request && operation.Messages.Count > 1 && IsBareResponse(style))
1195 TryGetNonMessageParameterType(operation.Messages[1], operation, false, out dummy);
1199 void ValidateGETHasNoBody(OperationDescription operation, string method)
1201 if (method == GET)
1203 if (!IsUntypedMessage(operation.Messages[0]) && operation.Messages[0].Body.Parts.Count != 0)
1205 if (!IsTypedMessage(operation.Messages[0]))
1207 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
1208 SR2.GetString(SR2.GETCannotHaveBody, operation.Name, operation.DeclaringContract.Name, operation.Messages[0].Body.Parts[0].Name)));
1210 else
1212 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
1213 SR2.GetString(SR2.GETCannotHaveMCParameter, operation.Name, operation.DeclaringContract.Name, operation.Messages[0].MessageType.Name)));
1219 void ValidateContract(ServiceEndpoint endpoint)
1221 foreach (OperationDescription od in endpoint.Contract.Operations)
1223 ValidateNoOperationHasEncodedXmlSerializer(od);
1224 ValidateNoMessageContractHeaders(od.Messages[0], od.Name, endpoint.Contract.Name);
1225 ValidateNoBareMessageContractWithMultipleParts(od.Messages[0], od.Name, endpoint.Contract.Name);
1226 ValidateNoMessageContractWithStream(od.Messages[0], od.Name, endpoint.Contract.Name);
1227 if (od.Messages.Count > 1)
1229 ValidateNoMessageContractHeaders(od.Messages[1], od.Name, endpoint.Contract.Name);
1230 ValidateNoBareMessageContractWithMultipleParts(od.Messages[1], od.Name, endpoint.Contract.Name);
1231 ValidateNoMessageContractWithStream(od.Messages[1], od.Name, endpoint.Contract.Name);
1236 internal static bool IsXmlSerializerFaultFormat(OperationDescription operationDescription)
1238 XmlSerializerOperationBehavior xsob = operationDescription.Behaviors.Find<XmlSerializerOperationBehavior>();
1239 return (xsob != null && xsob.XmlSerializerFormatAttribute.SupportFaults);
1242 void ValidateNoMessageContractWithStream(MessageDescription md, string opName, string contractName)
1244 if (IsTypedMessage(md))
1246 foreach (MessagePartDescription description in md.Body.Parts)
1248 if (description.Type == typeof(Stream))
1250 throw System.ServiceModel.DiagnosticUtility.ExceptionUtility.ThrowHelperError(
1251 new InvalidOperationException(System.ServiceModel.SR2.GetString(System.ServiceModel.SR2.StreamBodyMemberNotSupported, this.GetType().ToString(), contractName, opName, md.MessageType.ToString(), description.Name)));
1257 void ValidateNoOperationHasEncodedXmlSerializer(OperationDescription od)
1259 XmlSerializerOperationBehavior xsob = od.Behaviors.Find<XmlSerializerOperationBehavior>();
1260 if (xsob != null && (xsob.XmlSerializerFormatAttribute.Style == OperationFormatStyle.Rpc || xsob.XmlSerializerFormatAttribute.IsEncoded))
1262 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR2.GetString(SR2.RpcEncodedNotSupportedForNoneMessageVersion, od.Name, od.DeclaringContract.Name, od.DeclaringContract.Namespace)));
1266 void ValidateNoBareMessageContractWithMultipleParts(MessageDescription md, string opName, string contractName)
1268 if (IsTypedMessage(md) && md.Body.WrapperName == null)
1270 if (md.Body.Parts.Count > 1)
1272 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
1273 SR2.GetString(SR2.InvalidMessageContractWithoutWrapperName, opName, contractName, md.MessageType)));
1275 if (md.Body.Parts.Count == 1 && md.Body.Parts[0].Multiple)
1277 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR2.GetString(SR2.MCAtMostOneRequestBodyParameterAllowedForUnwrappedMessages, opName, contractName, md.MessageType)));
1282 void ValidateNoMessageContractHeaders(MessageDescription md, string opName, string contractName)
1284 if (md.Headers.Count != 0)
1286 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
1287 SR2.GetString(SR2.InvalidMethodWithSOAPHeaders, opName, contractName)));
1291 internal class MessagePassthroughFormatter : IClientMessageFormatter, IDispatchMessageFormatter
1293 public object DeserializeReply(Message message, object[] parameters)
1295 return message;
1298 public void DeserializeRequest(Message message, object[] parameters)
1300 parameters[0] = message;
1303 public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result)
1305 return result as Message;
1308 public Message SerializeRequest(MessageVersion messageVersion, object[] parameters)
1310 return parameters[0] as Message;
1314 static internal JavascriptCallbackResponseMessageProperty TrySetupJavascriptCallback(string callbackParameterName)
1316 JavascriptCallbackResponseMessageProperty javascriptProperty = null;
1317 if (!String.IsNullOrEmpty(callbackParameterName) &&
1318 !OperationContext.Current.OutgoingMessageProperties.TryGetValue<JavascriptCallbackResponseMessageProperty>(JavascriptCallbackResponseMessageProperty.Name, out javascriptProperty))
1320 UriTemplateMatch match = WebOperationContext.Current.IncomingRequest.UriTemplateMatch;
1321 if (match != null &&
1322 match.QueryParameters.AllKeys.Contains(callbackParameterName))
1324 string callbackName = match.QueryParameters[callbackParameterName];
1326 if (!String.IsNullOrEmpty(callbackName))
1328 javascriptProperty = new JavascriptCallbackResponseMessageProperty
1330 CallbackFunctionName = callbackName
1332 OperationContext.Current.OutgoingMessageProperties.Add(JavascriptCallbackResponseMessageProperty.Name, javascriptProperty);
1336 return javascriptProperty;