You've already forked linux-packaging-mono
Imported Upstream version 4.0.0~alpha1
Former-commit-id: 806294f5ded97629b74c85c09952f2a74fe182d9
This commit is contained in:
@ -0,0 +1,33 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
namespace System.ServiceModel.Dispatcher
|
||||
{
|
||||
using System;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Description;
|
||||
|
||||
class CompositeClientFormatter : IClientMessageFormatter
|
||||
{
|
||||
IClientMessageFormatter reply;
|
||||
IClientMessageFormatter request;
|
||||
public CompositeClientFormatter(IClientMessageFormatter request, IClientMessageFormatter reply)
|
||||
{
|
||||
this.request = request;
|
||||
this.reply = reply;
|
||||
}
|
||||
|
||||
public object DeserializeReply(Message message, object[] parameters)
|
||||
{
|
||||
return this.reply.DeserializeReply(message, parameters);
|
||||
}
|
||||
|
||||
public Message SerializeRequest(MessageVersion messageVersion, object[] parameters)
|
||||
{
|
||||
return this.request.SerializeRequest(messageVersion, parameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,33 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
namespace System.ServiceModel.Dispatcher
|
||||
{
|
||||
using System;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Description;
|
||||
|
||||
class CompositeDispatchFormatter : IDispatchMessageFormatter
|
||||
{
|
||||
IDispatchMessageFormatter reply;
|
||||
IDispatchMessageFormatter request;
|
||||
public CompositeDispatchFormatter(IDispatchMessageFormatter request, IDispatchMessageFormatter reply)
|
||||
{
|
||||
this.request = request;
|
||||
this.reply = reply;
|
||||
}
|
||||
|
||||
public void DeserializeRequest(Message message, object[] parameters)
|
||||
{
|
||||
this.request.DeserializeRequest(message, parameters);
|
||||
}
|
||||
|
||||
public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result)
|
||||
{
|
||||
return this.reply.SerializeReply(messageVersion, parameters, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,92 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace System.ServiceModel.Dispatcher
|
||||
{
|
||||
using System.Collections;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Description;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Reflection;
|
||||
using System.Xml;
|
||||
using System.ServiceModel.Diagnostics;
|
||||
using System.Net;
|
||||
using System.ServiceModel.Dispatcher;
|
||||
using System.ServiceModel.Web;
|
||||
|
||||
class ContentTypeSettingClientMessageFormatter : IClientMessageFormatter
|
||||
{
|
||||
IClientMessageFormatter innerFormatter;
|
||||
string outgoingContentType;
|
||||
|
||||
public ContentTypeSettingClientMessageFormatter(string outgoingContentType, IClientMessageFormatter innerFormatter)
|
||||
{
|
||||
if (outgoingContentType == null)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("outgoingContentType");
|
||||
}
|
||||
if (innerFormatter == null)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("innerFormatter");
|
||||
}
|
||||
this.outgoingContentType = outgoingContentType;
|
||||
this.innerFormatter = innerFormatter;
|
||||
}
|
||||
|
||||
public object DeserializeReply(Message message, object[] parameters)
|
||||
{
|
||||
return this.innerFormatter.DeserializeReply(message, parameters);
|
||||
}
|
||||
|
||||
public Message SerializeRequest(MessageVersion messageVersion, object[] parameters)
|
||||
{
|
||||
Message message = this.innerFormatter.SerializeRequest(messageVersion, parameters);
|
||||
if (message != null)
|
||||
{
|
||||
AddRequestContentTypeProperty(message, this.outgoingContentType);
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
static void AddRequestContentTypeProperty(Message message, string contentType)
|
||||
{
|
||||
if (message == null)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("message");
|
||||
}
|
||||
if (contentType == null)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contentType");
|
||||
}
|
||||
if (OperationContext.Current != null && OperationContext.Current.HasOutgoingMessageProperties)
|
||||
{
|
||||
if (string.IsNullOrEmpty(WebOperationContext.Current.OutgoingRequest.ContentType))
|
||||
{
|
||||
WebOperationContext.Current.OutgoingRequest.ContentType = contentType;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
object prop;
|
||||
message.Properties.TryGetValue(HttpRequestMessageProperty.Name, out prop);
|
||||
HttpRequestMessageProperty httpProperty;
|
||||
if (prop != null)
|
||||
{
|
||||
httpProperty = (HttpRequestMessageProperty) prop;
|
||||
}
|
||||
else
|
||||
{
|
||||
httpProperty = new HttpRequestMessageProperty();
|
||||
message.Properties.Add(HttpRequestMessageProperty.Name, httpProperty);
|
||||
}
|
||||
if (string.IsNullOrEmpty(httpProperty.Headers[HttpRequestHeader.ContentType]))
|
||||
{
|
||||
httpProperty.Headers[HttpRequestHeader.ContentType] = contentType;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace System.ServiceModel.Dispatcher
|
||||
{
|
||||
using System.Net;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Web;
|
||||
|
||||
class ContentTypeSettingDispatchMessageFormatter : IDispatchMessageFormatter
|
||||
{
|
||||
IDispatchMessageFormatter innerFormatter;
|
||||
string outgoingContentType;
|
||||
|
||||
public ContentTypeSettingDispatchMessageFormatter(string outgoingContentType, IDispatchMessageFormatter innerFormatter)
|
||||
{
|
||||
if (outgoingContentType == null)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("outgoingContentType");
|
||||
}
|
||||
if (innerFormatter == null)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("innerFormatter");
|
||||
}
|
||||
this.outgoingContentType = outgoingContentType;
|
||||
this.innerFormatter = innerFormatter;
|
||||
}
|
||||
|
||||
public void DeserializeRequest(Message message, object[] parameters)
|
||||
{
|
||||
this.innerFormatter.DeserializeRequest(message, parameters);
|
||||
}
|
||||
|
||||
public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result)
|
||||
{
|
||||
Message message = this.innerFormatter.SerializeReply(messageVersion, parameters, result);
|
||||
if (message != null)
|
||||
{
|
||||
AddResponseContentTypeProperty(message, this.outgoingContentType);
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
static void AddResponseContentTypeProperty(Message message, string contentType)
|
||||
{
|
||||
if (message == null)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("message");
|
||||
}
|
||||
if (contentType == null)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contentType");
|
||||
}
|
||||
if (OperationContext.Current != null && OperationContext.Current.HasOutgoingMessageProperties)
|
||||
{
|
||||
if (string.IsNullOrEmpty(WebOperationContext.Current.OutgoingResponse.ContentType))
|
||||
{
|
||||
WebOperationContext.Current.OutgoingResponse.ContentType = contentType;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
object prop;
|
||||
message.Properties.TryGetValue(HttpResponseMessageProperty.Name, out prop);
|
||||
HttpResponseMessageProperty httpProperty;
|
||||
if (prop != null)
|
||||
{
|
||||
httpProperty = (HttpResponseMessageProperty) prop;
|
||||
}
|
||||
else
|
||||
{
|
||||
httpProperty = new HttpResponseMessageProperty();
|
||||
message.Properties.Add(HttpResponseMessageProperty.Name, httpProperty);
|
||||
}
|
||||
if (string.IsNullOrEmpty(httpProperty.Headers[HttpResponseHeader.ContentType]))
|
||||
{
|
||||
httpProperty.Headers[HttpResponseHeader.ContentType] = contentType;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,76 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
namespace System.ServiceModel.Dispatcher
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Description;
|
||||
using System.Globalization;
|
||||
|
||||
class DemultiplexingClientMessageFormatter : IClientMessageFormatter
|
||||
{
|
||||
IClientMessageFormatter defaultFormatter;
|
||||
Dictionary<WebContentFormat, IClientMessageFormatter> formatters;
|
||||
string supportedFormats;
|
||||
|
||||
public DemultiplexingClientMessageFormatter(IDictionary<WebContentFormat, IClientMessageFormatter> formatters, IClientMessageFormatter defaultFormatter)
|
||||
{
|
||||
if (formatters == null)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("formatters");
|
||||
}
|
||||
this.formatters = new Dictionary<WebContentFormat, IClientMessageFormatter>();
|
||||
foreach (WebContentFormat key in formatters.Keys)
|
||||
{
|
||||
this.formatters.Add(key, formatters[key]);
|
||||
}
|
||||
this.defaultFormatter = defaultFormatter;
|
||||
}
|
||||
|
||||
public object DeserializeReply(Message message, object[] parameters)
|
||||
{
|
||||
if (message == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
WebContentFormat format;
|
||||
IClientMessageFormatter selectedFormatter;
|
||||
if (DemultiplexingDispatchMessageFormatter.TryGetEncodingFormat(message, out format))
|
||||
{
|
||||
this.formatters.TryGetValue(format, out selectedFormatter);
|
||||
if (selectedFormatter == null)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR2.GetString(SR2.UnrecognizedHttpMessageFormat, format, GetSupportedFormats())));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedFormatter = this.defaultFormatter;
|
||||
if (selectedFormatter == null)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR2.GetString(SR2.MessageFormatPropertyNotFound3)));
|
||||
}
|
||||
}
|
||||
return selectedFormatter.DeserializeReply(message, parameters);
|
||||
}
|
||||
|
||||
public Message SerializeRequest(MessageVersion messageVersion, object[] parameters)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR2.GetString(SR2.SerializingRequestNotSupportedByFormatter, this)));
|
||||
}
|
||||
|
||||
string GetSupportedFormats()
|
||||
{
|
||||
if (this.supportedFormats == null)
|
||||
{
|
||||
this.supportedFormats = DemultiplexingDispatchMessageFormatter.GetSupportedFormats(this.formatters.Keys);
|
||||
}
|
||||
return this.supportedFormats;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,108 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
namespace System.ServiceModel.Dispatcher
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Description;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
|
||||
class DemultiplexingDispatchMessageFormatter : IDispatchMessageFormatter
|
||||
{
|
||||
IDispatchMessageFormatter defaultFormatter;
|
||||
Dictionary<WebContentFormat, IDispatchMessageFormatter> formatters;
|
||||
string supportedFormats;
|
||||
|
||||
public DemultiplexingDispatchMessageFormatter(IDictionary<WebContentFormat, IDispatchMessageFormatter> formatters, IDispatchMessageFormatter defaultFormatter)
|
||||
{
|
||||
if (formatters == null)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("formatters");
|
||||
}
|
||||
this.formatters = new Dictionary<WebContentFormat, IDispatchMessageFormatter>();
|
||||
foreach (WebContentFormat key in formatters.Keys)
|
||||
{
|
||||
this.formatters.Add(key, formatters[key]);
|
||||
}
|
||||
this.defaultFormatter = defaultFormatter;
|
||||
}
|
||||
|
||||
public void DeserializeRequest(Message message, object[] parameters)
|
||||
{
|
||||
if (message == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
WebContentFormat format;
|
||||
IDispatchMessageFormatter selectedFormatter;
|
||||
if (TryGetEncodingFormat(message, out format))
|
||||
{
|
||||
this.formatters.TryGetValue(format, out selectedFormatter);
|
||||
if (selectedFormatter == null)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR2.GetString(SR2.UnrecognizedHttpMessageFormat, format, GetSupportedFormats())));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedFormatter = this.defaultFormatter;
|
||||
if (selectedFormatter == null)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR2.GetString(SR2.MessageFormatPropertyNotFound3)));
|
||||
}
|
||||
}
|
||||
selectedFormatter.DeserializeRequest(message, parameters);
|
||||
}
|
||||
|
||||
public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR2.GetString(SR2.SerializingReplyNotSupportedByFormatter, this)));
|
||||
}
|
||||
|
||||
internal static string GetSupportedFormats(IEnumerable<WebContentFormat> formats)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int i = 0;
|
||||
foreach (WebContentFormat format in formats)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
sb.Append(CultureInfo.CurrentCulture.TextInfo.ListSeparator);
|
||||
sb.Append(" ");
|
||||
}
|
||||
sb.Append("'" + format.ToString() + "'");
|
||||
++i;
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
internal static bool TryGetEncodingFormat(Message message, out WebContentFormat format)
|
||||
{
|
||||
object prop;
|
||||
message.Properties.TryGetValue(WebBodyFormatMessageProperty.Name, out prop);
|
||||
WebBodyFormatMessageProperty formatProperty = prop as WebBodyFormatMessageProperty;
|
||||
if (formatProperty == null)
|
||||
{
|
||||
format = WebContentFormat.Default;
|
||||
return false;
|
||||
}
|
||||
format = formatProperty.Format;
|
||||
return true;
|
||||
}
|
||||
|
||||
string GetSupportedFormats()
|
||||
{
|
||||
if (this.supportedFormats == null)
|
||||
{
|
||||
this.supportedFormats = GetSupportedFormats(this.formatters.Keys);
|
||||
}
|
||||
return this.supportedFormats;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,235 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
#pragma warning disable 1634, 1691
|
||||
namespace System.ServiceModel.Description
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Mime;
|
||||
using System.Runtime;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Dispatcher;
|
||||
using System.ServiceModel.Web;
|
||||
using System.Diagnostics;
|
||||
using System.ServiceModel.Diagnostics;
|
||||
|
||||
class FormatSelectingMessageInspector : IDispatchMessageInspector
|
||||
{
|
||||
static readonly IEnumerable<string> wildcardMediaTypes = new List<string>() { "application", "text" };
|
||||
|
||||
List<MultiplexingFormatMapping> mappings;
|
||||
Dictionary<string, MultiplexingDispatchMessageFormatter> formatters;
|
||||
Dictionary<string, NameValueCache<FormatContentTypePair>> caches;
|
||||
bool automaticFormatSelectionEnabled;
|
||||
|
||||
// There are technically an infinite number of valid accept headers for just xml and json,
|
||||
// but to prevent DOS attacks, we need to set an upper limit. It is assumed that there would
|
||||
// never be more than two dozen valid accept headers actually used out in the wild.
|
||||
static readonly int maxCachedAcceptHeaders = 25;
|
||||
|
||||
public FormatSelectingMessageInspector(WebHttpBehavior webHttpBehavior, List<MultiplexingFormatMapping> mappings)
|
||||
{
|
||||
if (webHttpBehavior == null)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("webHttpBehavior");
|
||||
}
|
||||
if (mappings == null)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("mappings");
|
||||
}
|
||||
|
||||
this.automaticFormatSelectionEnabled = webHttpBehavior.AutomaticFormatSelectionEnabled;
|
||||
|
||||
this.formatters = new Dictionary<string, MultiplexingDispatchMessageFormatter>();
|
||||
|
||||
this.caches = new Dictionary<string, NameValueCache<FormatContentTypePair>>();
|
||||
|
||||
this.mappings = mappings;
|
||||
}
|
||||
|
||||
public void RegisterOperation(string operationName, MultiplexingDispatchMessageFormatter formatter)
|
||||
{
|
||||
if (formatter == null)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("formatter");
|
||||
}
|
||||
Fx.Assert(!this.formatters.ContainsKey(operationName), "An operation should only be registered once.");
|
||||
this.formatters.Add(operationName, formatter);
|
||||
this.caches.Add(operationName, new NameValueCache<FormatContentTypePair>(maxCachedAcceptHeaders));
|
||||
}
|
||||
|
||||
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
|
||||
{
|
||||
if (this.automaticFormatSelectionEnabled)
|
||||
{
|
||||
MessageProperties messageProperties = OperationContext.Current.IncomingMessageProperties;
|
||||
if (messageProperties.ContainsKey(WebHttpDispatchOperationSelector.HttpOperationNamePropertyName))
|
||||
{
|
||||
string operationName = messageProperties[WebHttpDispatchOperationSelector.HttpOperationNamePropertyName] as string;
|
||||
if (!string.IsNullOrEmpty(operationName) && this.formatters.ContainsKey(operationName))
|
||||
{
|
||||
|
||||
string acceptHeader = WebOperationContext.Current.IncomingRequest.Accept;
|
||||
if (!string.IsNullOrEmpty(acceptHeader))
|
||||
{
|
||||
if (TrySetFormatFromCache(operationName, acceptHeader) ||
|
||||
TrySetFormatFromAcceptHeader(operationName, acceptHeader, true /* matchCharSet */) ||
|
||||
TrySetFormatFromAcceptHeader(operationName, acceptHeader, false /* matchCharSet */))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (TrySetFormatFromContentType(operationName))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
SetFormatFromDefault(operationName);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void BeforeSendReply(ref Message reply, object correlationState)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
bool TrySetFormatFromCache(string operationName, string acceptHeader)
|
||||
{
|
||||
Fx.Assert(this.caches.ContainsKey(operationName), "The calling method is responsible for ensuring that the 'operationName' key exists in the caches dictionary.");
|
||||
Fx.Assert(acceptHeader != null, "The calling method is responsible for ensuring that 'acceptHeader' is not null");
|
||||
|
||||
FormatContentTypePair pair = caches[operationName].Lookup(acceptHeader.ToUpperInvariant());
|
||||
if (pair != null)
|
||||
{
|
||||
SetFormatAndContentType(pair.Format, pair.ContentType);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase", Justification = "Given that media types are generally in lowercase, it is awkward to normalize to uppercase.")]
|
||||
bool TrySetFormatFromAcceptHeader(string operationName, string acceptHeader, bool matchCharSet)
|
||||
{
|
||||
Fx.Assert(this.formatters.ContainsKey(operationName), "The calling method is responsible for ensuring that the 'operationName' key exists in the formatters dictionary.");
|
||||
|
||||
IList<ContentType> acceptHeaderElements = WebOperationContext.Current.IncomingRequest.GetAcceptHeaderElements();
|
||||
|
||||
for (int i = 0; i < acceptHeaderElements.Count; i++)
|
||||
{
|
||||
string[] typeAndSubType = acceptHeaderElements[i].MediaType.Split('/');
|
||||
string type = typeAndSubType[0].Trim().ToLowerInvariant();
|
||||
string subType = typeAndSubType[1].Trim();
|
||||
|
||||
if ((subType[0] == '*' && subType.Length == 1) &&
|
||||
((type[0] == '*' && type.Length == 1) ||
|
||||
wildcardMediaTypes.Contains(type)))
|
||||
{
|
||||
SetFormatFromDefault(operationName, acceptHeader);
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach (MultiplexingFormatMapping mapping in mappings)
|
||||
{
|
||||
ContentType contentType;
|
||||
WebMessageFormat format = mapping.MessageFormat;
|
||||
if (this.formatters[operationName].SupportsMessageFormat(format) &&
|
||||
mapping.CanFormatResponse(acceptHeaderElements[i], matchCharSet, out contentType))
|
||||
{
|
||||
string contentTypeStr = contentType.ToString();
|
||||
this.caches[operationName].AddOrUpdate(acceptHeader.ToUpperInvariant(), new FormatContentTypePair(format, contentTypeStr));
|
||||
SetFormatAndContentType(format, contentTypeStr);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TrySetFormatFromContentType(string operationName)
|
||||
{
|
||||
Fx.Assert(this.formatters.ContainsKey(operationName), "The calling method is responsible for ensuring that the 'operationName' key exists in the formatters dictionary.");
|
||||
|
||||
string contentTypeStr = WebOperationContext.Current.IncomingRequest.ContentType;
|
||||
if (contentTypeStr != null)
|
||||
{
|
||||
ContentType contentType = Web.Utility.GetContentType(contentTypeStr);
|
||||
if (contentType != null)
|
||||
{
|
||||
foreach (MultiplexingFormatMapping mapping in mappings)
|
||||
{
|
||||
ContentType responseContentType;
|
||||
if (this.formatters[operationName].SupportsMessageFormat(mapping.MessageFormat) &&
|
||||
mapping.CanFormatResponse(contentType, false, out responseContentType))
|
||||
{
|
||||
SetFormatAndContentType(mapping.MessageFormat, responseContentType.ToString());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void SetFormatFromDefault(string operationName)
|
||||
{
|
||||
SetFormatFromDefault(operationName, null);
|
||||
}
|
||||
|
||||
void SetFormatFromDefault(string operationName, string acceptHeader)
|
||||
{
|
||||
Fx.Assert(this.formatters.ContainsKey(operationName), "The calling method is responsible for ensuring that the 'operationName' key exists in the formatters dictionary.");
|
||||
WebMessageFormat format = this.formatters[operationName].DefaultFormat;
|
||||
|
||||
if (!string.IsNullOrEmpty(acceptHeader))
|
||||
{
|
||||
this.caches[operationName].AddOrUpdate(acceptHeader.ToUpperInvariant(), new FormatContentTypePair(format, null));
|
||||
}
|
||||
|
||||
WebOperationContext.Current.OutgoingResponse.Format = format;
|
||||
|
||||
if (DiagnosticUtility.ShouldTraceInformation)
|
||||
{
|
||||
TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.AutomaticFormatSelectedOperationDefault, SR2.GetString(SR2.TraceCodeAutomaticFormatSelectedOperationDefault, format.ToString()));
|
||||
}
|
||||
}
|
||||
|
||||
void SetFormatAndContentType(WebMessageFormat format, string contentType)
|
||||
{
|
||||
OutgoingWebResponseContext outgoingResponse = WebOperationContext.Current.OutgoingResponse;
|
||||
outgoingResponse.Format = format;
|
||||
outgoingResponse.AutomatedFormatSelectionContentType = contentType;
|
||||
|
||||
if (DiagnosticUtility.ShouldTraceInformation)
|
||||
{
|
||||
TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.AutomaticFormatSelectedRequestBased, SR2.GetString(SR2.TraceCodeAutomaticFormatSelectedRequestBased, format.ToString(), contentType));
|
||||
}
|
||||
}
|
||||
|
||||
class FormatContentTypePair
|
||||
{
|
||||
WebMessageFormat format;
|
||||
string contentType;
|
||||
|
||||
public FormatContentTypePair(WebMessageFormat format, string contentType)
|
||||
{
|
||||
this.format = format;
|
||||
this.contentType = contentType;
|
||||
}
|
||||
|
||||
public WebMessageFormat Format
|
||||
{
|
||||
get { return this.format; }
|
||||
}
|
||||
|
||||
public string ContentType
|
||||
{
|
||||
get { return this.contentType; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
427
external/referencesource/System.ServiceModel.Web/System/ServiceModel/Dispatcher/HelpHtmlBuilder.cs
vendored
Normal file
427
external/referencesource/System.ServiceModel.Web/System/ServiceModel/Dispatcher/HelpHtmlBuilder.cs
vendored
Normal file
@ -0,0 +1,427 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace System.ServiceModel.Dispatcher
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Runtime.Serialization.Json;
|
||||
using System.ServiceModel.Description;
|
||||
using System.ServiceModel.Web;
|
||||
using System.ServiceModel.Web.Configuration;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
using System.Globalization;
|
||||
using System.Web;
|
||||
using System.Xml.Schema;
|
||||
|
||||
class HelpHtmlBuilder
|
||||
{
|
||||
const string HelpOperationPageUrl = "help/operations/{0}";
|
||||
const string HtmlHtmlElementName = "{http://www.w3.org/1999/xhtml}html";
|
||||
const string HtmlHeadElementName = "{http://www.w3.org/1999/xhtml}head";
|
||||
const string HtmlTitleElementName = "{http://www.w3.org/1999/xhtml}title";
|
||||
const string HtmlBodyElementName = "{http://www.w3.org/1999/xhtml}body";
|
||||
const string HtmlBrElementName = "{http://www.w3.org/1999/xhtml}br";
|
||||
const string HtmlPElementName = "{http://www.w3.org/1999/xhtml}p";
|
||||
const string HtmlTableElementName = "{http://www.w3.org/1999/xhtml}table";
|
||||
const string HtmlTrElementName = "{http://www.w3.org/1999/xhtml}tr";
|
||||
const string HtmlThElementName = "{http://www.w3.org/1999/xhtml}th";
|
||||
const string HtmlTdElementName = "{http://www.w3.org/1999/xhtml}td";
|
||||
const string HtmlDivElementName = "{http://www.w3.org/1999/xhtml}div";
|
||||
const string HtmlAElementName = "{http://www.w3.org/1999/xhtml}a";
|
||||
const string HtmlPreElementName = "{http://www.w3.org/1999/xhtml}pre";
|
||||
const string HtmlClassAttributeName = "class";
|
||||
const string HtmlTitleAttributeName = "title";
|
||||
const string HtmlHrefAttributeName = "href";
|
||||
const string HtmlRelAttributeName = "rel";
|
||||
const string HtmlIdAttributeName = "id";
|
||||
const string HtmlNameAttributeName = "name";
|
||||
const string HtmlRowspanAttributeName = "rowspan";
|
||||
const string HtmlHeading1Class = "heading1";
|
||||
const string HtmlContentClass = "content";
|
||||
|
||||
const string HtmlRequestXmlId = "request-xml";
|
||||
const string HtmlRequestJsonId = "request-json";
|
||||
const string HtmlRequestSchemaId = "request-schema";
|
||||
const string HtmlResponseXmlId = "response-xml";
|
||||
const string HtmlResponseJsonId = "response-json";
|
||||
const string HtmlResponseSchemaId = "response-schema";
|
||||
const string HtmlOperationClass = "operation";
|
||||
|
||||
public static XDocument CreateHelpPage(Uri baseUri, IEnumerable<OperationHelpInformation> operations)
|
||||
{
|
||||
XDocument document = CreateBaseDocument(SR2.GetString(SR2.HelpPageOperationsAt, baseUri));
|
||||
XElement table = new XElement(HtmlTableElementName,
|
||||
new XElement(HtmlTrElementName,
|
||||
new XElement(HtmlThElementName, SR2.GetString(SR2.HelpPageUri)),
|
||||
new XElement(HtmlThElementName, SR2.GetString(SR2.HelpPageMethod)),
|
||||
new XElement(HtmlThElementName, SR2.GetString(SR2.HelpPageDescription))));
|
||||
|
||||
string lastOperation = null;
|
||||
XElement firstTr = null;
|
||||
int rowspan = 0;
|
||||
foreach (OperationHelpInformation operationHelpInfo in operations.OrderBy(o => FilterQueryVariables(o.UriTemplate)))
|
||||
{
|
||||
string operationUri = FilterQueryVariables(operationHelpInfo.UriTemplate);
|
||||
string description = operationHelpInfo.Description;
|
||||
if (String.IsNullOrEmpty(description))
|
||||
{
|
||||
description = SR2.GetString(SR2.HelpPageDefaultDescription, BuildFullUriTemplate(baseUri, operationHelpInfo.UriTemplate));
|
||||
}
|
||||
XElement tr = new XElement(HtmlTrElementName,
|
||||
new XElement(HtmlTdElementName, new XAttribute(HtmlTitleAttributeName, BuildFullUriTemplate(baseUri, operationHelpInfo.UriTemplate)),
|
||||
new XElement(HtmlAElementName,
|
||||
new XAttribute(HtmlRelAttributeName, HtmlOperationClass),
|
||||
new XAttribute(HtmlHrefAttributeName, String.Format(CultureInfo.InvariantCulture, HelpOperationPageUrl, operationHelpInfo.Name)), operationHelpInfo.Method)),
|
||||
new XElement(HtmlTdElementName, description));
|
||||
table.Add(tr);
|
||||
if (operationUri != lastOperation)
|
||||
{
|
||||
XElement td = new XElement(HtmlTdElementName, operationUri == lastOperation ? String.Empty : operationUri);
|
||||
tr.AddFirst(td);
|
||||
if (firstTr != null && rowspan > 1)
|
||||
{
|
||||
firstTr.Descendants(HtmlTdElementName).First().Add(new XAttribute(HtmlRowspanAttributeName, rowspan));
|
||||
}
|
||||
firstTr = tr;
|
||||
rowspan = 0;
|
||||
lastOperation = operationUri;
|
||||
}
|
||||
++rowspan;
|
||||
}
|
||||
if (firstTr != null && rowspan > 1)
|
||||
{
|
||||
firstTr.Descendants(HtmlTdElementName).First().Add(new XAttribute(HtmlRowspanAttributeName, rowspan));
|
||||
}
|
||||
document.Descendants(HtmlBodyElementName).First().Add(new XElement(HtmlDivElementName, new XAttribute(HtmlIdAttributeName, HtmlContentClass),
|
||||
new XElement(HtmlPElementName, new XAttribute(HtmlClassAttributeName, HtmlHeading1Class), SR2.GetString(SR2.HelpPageOperationsAt, baseUri)),
|
||||
new XElement(HtmlPElementName, SR2.GetString(SR2.HelpPageStaticText)),
|
||||
table));
|
||||
return document;
|
||||
}
|
||||
|
||||
public static XDocument CreateOperationHelpPage(Uri baseUri, OperationHelpInformation operationInfo)
|
||||
{
|
||||
XDocument document = CreateBaseDocument(SR2.GetString(SR2.HelpPageReferenceFor, BuildFullUriTemplate(baseUri, operationInfo.UriTemplate)));
|
||||
XElement table = new XElement(HtmlTableElementName,
|
||||
new XElement(HtmlTrElementName,
|
||||
new XElement(HtmlThElementName, SR2.GetString(SR2.HelpPageMessageDirection)),
|
||||
new XElement(HtmlThElementName, SR2.GetString(SR2.HelpPageFormat)),
|
||||
new XElement(HtmlThElementName, SR2.GetString(SR2.HelpPageBody))));
|
||||
|
||||
RenderMessageInformation(table, operationInfo, true);
|
||||
RenderMessageInformation(table, operationInfo, false);
|
||||
|
||||
XElement div = new XElement(HtmlDivElementName, new XAttribute(HtmlIdAttributeName, HtmlContentClass),
|
||||
new XElement(HtmlPElementName, new XAttribute(HtmlClassAttributeName, HtmlHeading1Class), SR2.GetString(SR2.HelpPageReferenceFor, BuildFullUriTemplate(baseUri, operationInfo.UriTemplate))),
|
||||
new XElement(HtmlPElementName, operationInfo.Description),
|
||||
XElement.Parse(SR2.GetString(SR2.HelpPageOperationUri, HttpUtility.HtmlEncode(BuildFullUriTemplate(baseUri, operationInfo.UriTemplate)))),
|
||||
XElement.Parse(SR2.GetString(SR2.HelpPageOperationMethod, HttpUtility.HtmlEncode(operationInfo.Method))));
|
||||
if (!String.IsNullOrEmpty(operationInfo.JavascriptCallbackParameterName))
|
||||
{
|
||||
div.Add(XElement.Parse(SR2.GetString(SR2.HelpPageCallbackText, HttpUtility.HtmlEncode(operationInfo.JavascriptCallbackParameterName))), table);
|
||||
}
|
||||
else
|
||||
{
|
||||
div.Add(table);
|
||||
}
|
||||
document.Descendants(HtmlBodyElementName).First().Add(div);
|
||||
|
||||
CreateOperationSamples(document.Descendants(HtmlDivElementName).First(), operationInfo);
|
||||
|
||||
return document;
|
||||
}
|
||||
|
||||
public static XDocument CreateMethodNotAllowedPage(Uri helpUri)
|
||||
{
|
||||
XDocument document = CreateBaseDocument(SR2.GetString(SR2.HelpPageTitleText));
|
||||
|
||||
XElement div = new XElement(HtmlDivElementName, new XAttribute(HtmlIdAttributeName, HtmlContentClass),
|
||||
new XElement(HtmlPElementName, new XAttribute(HtmlClassAttributeName, HtmlHeading1Class), SR2.GetString(SR2.HelpPageTitleText)));
|
||||
if (helpUri == null)
|
||||
{
|
||||
div.Add(new XElement(HtmlPElementName, SR2.GetString(SR2.HelpPageMethodNotAllowed)));
|
||||
}
|
||||
else
|
||||
{
|
||||
div.Add(XElement.Parse(SR2.GetString(SR2.HelpPageMethodNotAllowedWithLink, HttpUtility.HtmlEncode(helpUri.AbsoluteUri))));
|
||||
}
|
||||
document.Descendants(HtmlBodyElementName).First().Add(div);
|
||||
return document;
|
||||
}
|
||||
|
||||
public static XDocument CreateServerErrorPage(Uri helpUri, Exception error)
|
||||
{
|
||||
XDocument document = CreateBaseDocument(SR2.GetString(SR2.HelpPageRequestErrorTitle));
|
||||
|
||||
XElement div = new XElement(HtmlDivElementName, new XAttribute(HtmlIdAttributeName, HtmlContentClass),
|
||||
new XElement(HtmlPElementName, new XAttribute(HtmlClassAttributeName, HtmlHeading1Class), SR2.GetString(SR2.HelpPageRequestErrorTitle)));
|
||||
if (helpUri == null)
|
||||
{
|
||||
if (error != null)
|
||||
{
|
||||
//TFS Bug 500275: it is not necessary to HtmlEncode the error.Message string here because XElement ctor will encode it.
|
||||
div.Add(new XElement(HtmlPElementName, SR2.GetString(SR2.HelpServerErrorProcessingRequestWithDetails, error.Message)));
|
||||
div.Add(new XElement(HtmlPElementName, error.StackTrace ?? String.Empty));
|
||||
}
|
||||
else
|
||||
{
|
||||
div.Add(new XElement(HtmlPElementName, SR2.GetString(SR2.HelpServerErrorProcessingRequest)));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string encodedHelpLink = HttpUtility.HtmlEncode(helpUri.AbsoluteUri);
|
||||
if (error != null)
|
||||
{
|
||||
//TFS Bug 500275: XElement.Parse does not HtmlEncode the string passed to it, so we need to encode it before calling Parse.
|
||||
string errorMessage = AppSettings.DisableHtmlErrorPageExceptionHtmlEncoding ? error.Message : HttpUtility.HtmlEncode(error.Message);
|
||||
div.Add(XElement.Parse(SR2.GetString(SR2.HelpServerErrorProcessingRequestWithDetailsAndLink, encodedHelpLink, errorMessage)));
|
||||
div.Add(new XElement(HtmlPElementName, error.StackTrace ?? String.Empty));
|
||||
}
|
||||
else
|
||||
{
|
||||
div.Add(XElement.Parse(SR2.GetString(SR2.HelpServerErrorProcessingRequestWithLink, encodedHelpLink)));
|
||||
}
|
||||
|
||||
}
|
||||
document.Descendants(HtmlBodyElementName).First().Add(div);
|
||||
return document;
|
||||
}
|
||||
|
||||
public static XDocument CreateEndpointNotFound(Uri helpUri)
|
||||
{
|
||||
XDocument document = CreateBaseDocument(SR2.GetString(SR2.HelpPageTitleText));
|
||||
|
||||
XElement div = new XElement(HtmlDivElementName, new XAttribute(HtmlIdAttributeName, HtmlContentClass),
|
||||
new XElement(HtmlPElementName, new XAttribute(HtmlClassAttributeName, HtmlHeading1Class), SR2.GetString(SR2.HelpPageTitleText)));
|
||||
if (helpUri == null)
|
||||
{
|
||||
div.Add(new XElement(HtmlPElementName, SR2.GetString(SR2.HelpPageEndpointNotFound)));
|
||||
}
|
||||
else
|
||||
{
|
||||
div.Add(XElement.Parse(SR2.GetString(SR2.HelpPageEndpointNotFoundWithLink, HttpUtility.HtmlEncode(helpUri.AbsoluteUri))));
|
||||
}
|
||||
document.Descendants(HtmlBodyElementName).First().Add(div);
|
||||
return document;
|
||||
}
|
||||
|
||||
public static XDocument CreateTransferRedirectPage(string originalTo, string newLocation)
|
||||
{
|
||||
XDocument document = CreateBaseDocument(SR2.GetString(SR2.HelpPageTitleText));
|
||||
|
||||
XElement div = new XElement(HtmlDivElementName, new XAttribute(HtmlIdAttributeName, HtmlContentClass),
|
||||
new XElement(HtmlPElementName, new XAttribute(HtmlClassAttributeName, HtmlHeading1Class), SR2.GetString(SR2.HelpPageTitleText)),
|
||||
XElement.Parse(SR2.GetString(SR2.HelpPageRedirect, HttpUtility.HtmlEncode(originalTo), HttpUtility.HtmlEncode(newLocation))));
|
||||
document.Descendants(HtmlBodyElementName).First().Add(div);
|
||||
return document;
|
||||
}
|
||||
|
||||
static XDocument CreateBaseDocument(string title)
|
||||
{
|
||||
return new XDocument(
|
||||
new XDocumentType("html", "-//W3C//DTD XHTML 1.0 Transitional//EN", "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd", null),
|
||||
new XElement(HtmlHtmlElementName,
|
||||
new XElement(HtmlHeadElementName,
|
||||
new XElement(HtmlTitleElementName, title),
|
||||
new XElement("{http://www.w3.org/1999/xhtml}style", SR2.GetString(SR2.HelpPageHtml))),
|
||||
new XElement(HtmlBodyElementName)));
|
||||
}
|
||||
|
||||
static string FilterQueryVariables(string uriTemplate)
|
||||
{
|
||||
int variablesIndex = uriTemplate.IndexOf('?');
|
||||
if (variablesIndex > 0)
|
||||
{
|
||||
return uriTemplate.Substring(0, variablesIndex);
|
||||
}
|
||||
return uriTemplate;
|
||||
}
|
||||
|
||||
static void RenderMessageInformation(XElement table, OperationHelpInformation operationInfo, bool isRequest)
|
||||
{
|
||||
MessageHelpInformation info = isRequest ? operationInfo.Request : operationInfo.Response;
|
||||
string direction = isRequest ? SR2.GetString(SR2.HelpPageRequest) : SR2.GetString(SR2.HelpPageResponse);
|
||||
string nonLocalizedDirection = isRequest ? HtmlRequestXmlId : HtmlResponseXmlId;
|
||||
|
||||
if (info.BodyDescription != null)
|
||||
{
|
||||
table.Add(new XElement(HtmlTrElementName,
|
||||
new XElement(HtmlTdElementName, direction),
|
||||
new XElement(HtmlTdElementName, info.FormatString),
|
||||
new XElement(HtmlTdElementName, info.BodyDescription)));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (info.XmlExample != null || info.Schema != null)
|
||||
{
|
||||
XElement contentTd;
|
||||
table.Add(new XElement(HtmlTrElementName,
|
||||
new XElement(HtmlTdElementName, direction),
|
||||
new XElement(HtmlTdElementName, "Xml"),
|
||||
contentTd = new XElement(HtmlTdElementName)));
|
||||
|
||||
if (info.XmlExample != null)
|
||||
{
|
||||
contentTd.Add(new XElement(HtmlAElementName, new XAttribute(HtmlHrefAttributeName, "#" + (isRequest ? HtmlRequestXmlId : HtmlResponseXmlId)), SR2.GetString(SR2.HelpPageExample)));
|
||||
if (info.Schema != null)
|
||||
{
|
||||
contentTd.Add(",");
|
||||
}
|
||||
}
|
||||
if (info.Schema != null)
|
||||
{
|
||||
contentTd.Add(new XElement(HtmlAElementName, new XAttribute(HtmlHrefAttributeName, "#" + (isRequest ? HtmlRequestSchemaId : HtmlResponseSchemaId)), SR2.GetString(SR2.HelpPageSchema)));
|
||||
}
|
||||
}
|
||||
if (info.JsonExample != null)
|
||||
{
|
||||
table.Add(new XElement(HtmlTrElementName,
|
||||
new XElement(HtmlTdElementName, direction),
|
||||
new XElement(HtmlTdElementName, "Json"),
|
||||
new XElement(HtmlTdElementName,
|
||||
new XElement(HtmlAElementName, new XAttribute(HtmlHrefAttributeName, "#" + (isRequest ? HtmlRequestJsonId : HtmlResponseJsonId)), SR2.GetString(SR2.HelpPageExample)))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void CreateOperationSamples(XElement element, OperationHelpInformation operationInfo)
|
||||
{
|
||||
if (operationInfo.Request.XmlExample != null)
|
||||
{
|
||||
element.Add(GenerateSampleXml(operationInfo.Request.XmlExample, SR2.GetString(SR2.HelpPageXmlRequest), HtmlRequestXmlId));
|
||||
}
|
||||
if (operationInfo.Request.JsonExample != null)
|
||||
{
|
||||
element.Add(AddSampleJson(operationInfo.Request.JsonExample, SR2.GetString(SR2.HelpPageJsonRequest), HtmlRequestJsonId));
|
||||
}
|
||||
if (operationInfo.Response.XmlExample != null)
|
||||
{
|
||||
element.Add(GenerateSampleXml(operationInfo.Response.XmlExample, SR2.GetString(SR2.HelpPageXmlResponse), HtmlResponseXmlId));
|
||||
}
|
||||
if (operationInfo.Response.JsonExample != null)
|
||||
{
|
||||
element.Add(AddSampleJson(operationInfo.Response.JsonExample, SR2.GetString(SR2.HelpPageJsonResponse), HtmlResponseJsonId));
|
||||
}
|
||||
|
||||
if (operationInfo.Request.Schema != null)
|
||||
{
|
||||
element.Add(GenerateSampleXml(XmlSchemaToXElement(operationInfo.Request.Schema), SR2.GetString(SR2.HelpPageRequestSchema), HtmlRequestSchemaId));
|
||||
int count = 0;
|
||||
foreach (XmlSchema schema in operationInfo.Request.SchemaSet.Schemas())
|
||||
{
|
||||
if (schema.TargetNamespace != operationInfo.Request.Schema.TargetNamespace)
|
||||
{
|
||||
element.Add(GenerateSampleXml(XmlSchemaToXElement(schema), ++count == 1 ? SR2.GetString(SR2.HelpPageAdditionalRequestSchema) : null, HtmlRequestSchemaId));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (operationInfo.Response.Schema != null)
|
||||
{
|
||||
element.Add(GenerateSampleXml(XmlSchemaToXElement(operationInfo.Response.Schema), SR2.GetString(SR2.HelpPageResponseSchema), HtmlResponseSchemaId));
|
||||
int count = 0;
|
||||
foreach (XmlSchema schema in operationInfo.Response.SchemaSet.Schemas())
|
||||
{
|
||||
if (schema.TargetNamespace != operationInfo.Response.Schema.TargetNamespace)
|
||||
{
|
||||
element.Add(GenerateSampleXml(XmlSchemaToXElement(schema), ++count == 1 ? SR2.GetString(SR2.HelpPageAdditionalResponseSchema) : null, HtmlResponseSchemaId));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static XElement XmlSchemaToXElement(XmlSchema schema)
|
||||
{
|
||||
XmlWriterSettings settings = new XmlWriterSettings
|
||||
{
|
||||
CloseOutput = false,
|
||||
Indent = true,
|
||||
};
|
||||
|
||||
XDocument schemaDocument = new XDocument();
|
||||
|
||||
using (XmlWriter writer = XmlWriter.Create(schemaDocument.CreateWriter(), settings))
|
||||
{
|
||||
schema.Write(writer);
|
||||
}
|
||||
return schemaDocument.Root;
|
||||
}
|
||||
|
||||
static XElement AddSample(object content, string title, string label)
|
||||
{
|
||||
if (String.IsNullOrEmpty(title))
|
||||
{
|
||||
return new XElement(HtmlPElementName,
|
||||
new XElement(HtmlPreElementName, new XAttribute(HtmlClassAttributeName, label), content));
|
||||
}
|
||||
else
|
||||
{
|
||||
return new XElement(HtmlPElementName,
|
||||
new XElement(HtmlAElementName, new XAttribute(HtmlNameAttributeName, "#" + label), title),
|
||||
new XElement(HtmlPreElementName, new XAttribute(HtmlClassAttributeName, label), content));
|
||||
}
|
||||
}
|
||||
|
||||
static XElement GenerateSampleXml(XElement content, string title, string label)
|
||||
{
|
||||
StringBuilder sample = new StringBuilder();
|
||||
using (XmlWriter writer = XmlTextWriter.Create(sample, new XmlWriterSettings { Indent = true, OmitXmlDeclaration = true }))
|
||||
{
|
||||
content.WriteTo(writer);
|
||||
}
|
||||
return AddSample(sample.ToString(), title, label);
|
||||
}
|
||||
|
||||
static XElement AddSampleJson(XElement content, string title, string label)
|
||||
{
|
||||
StringBuilder sample = new StringBuilder();
|
||||
using (MemoryStream stream = new MemoryStream())
|
||||
{
|
||||
using (XmlJsonWriter writer = new XmlJsonWriter())
|
||||
{
|
||||
writer.SetOutput(stream, Encoding.Unicode, false);
|
||||
content.WriteTo(writer);
|
||||
}
|
||||
stream.Position = 0;
|
||||
sample.Append(new StreamReader(stream, Encoding.Unicode).ReadToEnd());
|
||||
}
|
||||
int depth = 0;
|
||||
bool inString = false;
|
||||
for (int i = 0; i < sample.Length; ++i)
|
||||
{
|
||||
if (sample[i] == '"')
|
||||
{
|
||||
inString = !inString;
|
||||
}
|
||||
else if (sample[i] == '{')
|
||||
{
|
||||
sample.Insert(i + 1, "\n" + new String('\t', ++depth));
|
||||
i += depth + 1;
|
||||
}
|
||||
else if (sample[i] == ',' && !inString)
|
||||
{
|
||||
sample.Insert(i + 1, "\n" + new String('\t', depth));
|
||||
}
|
||||
else if (sample[i] == '}' && depth > 0)
|
||||
{
|
||||
sample.Insert(i, "\n" + new String('\t', --depth));
|
||||
i += depth + 1;
|
||||
}
|
||||
}
|
||||
return AddSample(sample.ToString(), title, label);
|
||||
}
|
||||
|
||||
static string BuildFullUriTemplate(Uri baseUri, string uriTemplate)
|
||||
{
|
||||
UriTemplate template = new UriTemplate(uriTemplate);
|
||||
Uri result = template.BindByPosition(baseUri, template.PathSegmentVariableNames.Concat(template.QueryValueVariableNames).Select(name => "{" + name + "}").ToArray());
|
||||
return result.ToString();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Net;
|
||||
using System.Runtime;
|
||||
using System.Web;
|
||||
using System.ServiceModel.Syndication;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Dispatcher;
|
||||
|
||||
namespace System.ServiceModel.Web
|
||||
{
|
||||
class HelpOperationInvoker : IOperationInvoker
|
||||
{
|
||||
HelpPage helpPage;
|
||||
IOperationInvoker unhandledDispatchOperation;
|
||||
|
||||
public const string OperationName = "HelpPageInvoke";
|
||||
|
||||
public HelpOperationInvoker(HelpPage helpPage, IOperationInvoker unhandledDispatchOperation)
|
||||
{
|
||||
this.helpPage = helpPage;
|
||||
this.unhandledDispatchOperation = unhandledDispatchOperation;
|
||||
}
|
||||
|
||||
public object[] AllocateInputs()
|
||||
{
|
||||
return new object[] { null };
|
||||
}
|
||||
|
||||
public object Invoke(object instance, object[] inputs, out object[] outputs)
|
||||
{
|
||||
outputs = null;
|
||||
UriTemplateMatch match = (UriTemplateMatch)OperationContext.Current.IncomingMessageProperties[IncomingWebRequestContext.UriTemplateMatchResultsPropertyName];
|
||||
return this.helpPage.Invoke(match);
|
||||
}
|
||||
|
||||
public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
|
||||
}
|
||||
|
||||
public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
|
||||
}
|
||||
|
||||
public bool IsSynchronous
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
}
|
||||
}
|
461
external/referencesource/System.ServiceModel.Web/System/ServiceModel/Dispatcher/HelpPage.cs
vendored
Normal file
461
external/referencesource/System.ServiceModel.Web/System/ServiceModel/Dispatcher/HelpPage.cs
vendored
Normal file
@ -0,0 +1,461 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace System.ServiceModel.Dispatcher
|
||||
{
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Runtime;
|
||||
using System.Runtime.Serialization;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Description;
|
||||
using System.ServiceModel.Syndication;
|
||||
using System.ServiceModel.Web;
|
||||
using System.Web;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
using System.Xml.Schema;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
class HelpPage
|
||||
{
|
||||
public const string OperationListHelpPageUriTemplate = "help";
|
||||
public const string OperationHelpPageUriTemplate = "help/operations/{operation}";
|
||||
const string HelpMethodName = "GetHelpPage";
|
||||
const string HelpOperationMethodName = "GetOperationHelpPage";
|
||||
|
||||
DateTime startupTime = DateTime.UtcNow;
|
||||
|
||||
Dictionary<string, OperationHelpInformation> operationInfoDictionary;
|
||||
NameValueCache<string> operationPageCache;
|
||||
NameValueCache<string> helpPageCache;
|
||||
|
||||
public HelpPage(WebHttpBehavior behavior, ContractDescription description)
|
||||
{
|
||||
this.operationInfoDictionary = new Dictionary<string, OperationHelpInformation>();
|
||||
this.operationPageCache = new NameValueCache<string>();
|
||||
this.helpPageCache = new NameValueCache<string>();
|
||||
foreach (OperationDescription od in description.Operations)
|
||||
{
|
||||
operationInfoDictionary.Add(od.Name, new OperationHelpInformation(behavior, od));
|
||||
}
|
||||
}
|
||||
|
||||
Message GetHelpPage()
|
||||
{
|
||||
Uri baseUri = UriTemplate.RewriteUri(OperationContext.Current.Channel.LocalAddress.Uri, WebOperationContext.Current.IncomingRequest.Headers[HttpRequestHeader.Host]);
|
||||
string helpPage = this.helpPageCache.Lookup(baseUri.Authority);
|
||||
if (String.IsNullOrEmpty(helpPage))
|
||||
{
|
||||
helpPage = HelpHtmlBuilder.CreateHelpPage(baseUri, operationInfoDictionary.Values).ToString();
|
||||
if (HttpContext.Current == null)
|
||||
{
|
||||
this.helpPageCache.AddOrUpdate(baseUri.Authority, helpPage);
|
||||
}
|
||||
}
|
||||
return WebOperationContext.Current.CreateTextResponse(helpPage, "text/html");
|
||||
}
|
||||
|
||||
Message GetOperationHelpPage(string operation)
|
||||
{
|
||||
Uri requestUri = UriTemplate.RewriteUri(WebOperationContext.Current.IncomingRequest.UriTemplateMatch.RequestUri, WebOperationContext.Current.IncomingRequest.Headers[HttpRequestHeader.Host]);
|
||||
string helpPage = this.operationPageCache.Lookup(requestUri.AbsoluteUri);
|
||||
if (String.IsNullOrEmpty(helpPage))
|
||||
{
|
||||
OperationHelpInformation operationInfo;
|
||||
if (this.operationInfoDictionary.TryGetValue(operation, out operationInfo))
|
||||
{
|
||||
Uri baseUri = UriTemplate.RewriteUri(OperationContext.Current.Channel.LocalAddress.Uri, WebOperationContext.Current.IncomingRequest.Headers[HttpRequestHeader.Host]);
|
||||
helpPage = HelpHtmlBuilder.CreateOperationHelpPage(baseUri, operationInfo).ToString();
|
||||
if (HttpContext.Current == null)
|
||||
{
|
||||
this.operationPageCache.AddOrUpdate(requestUri.AbsoluteUri, helpPage);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw System.ServiceModel.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new WebFaultException(HttpStatusCode.NotFound));
|
||||
}
|
||||
}
|
||||
return WebOperationContext.Current.CreateTextResponse(helpPage, "text/html");
|
||||
}
|
||||
|
||||
public static IEnumerable<KeyValuePair<UriTemplate, object>> GetOperationTemplatePairs()
|
||||
{
|
||||
return new KeyValuePair<UriTemplate, object>[]
|
||||
{
|
||||
new KeyValuePair<UriTemplate, object>(new UriTemplate(OperationListHelpPageUriTemplate), HelpMethodName),
|
||||
new KeyValuePair<UriTemplate, object>(new UriTemplate(OperationHelpPageUriTemplate), HelpOperationMethodName)
|
||||
};
|
||||
}
|
||||
|
||||
public object Invoke(UriTemplateMatch match)
|
||||
{
|
||||
if (HttpContext.Current != null)
|
||||
{
|
||||
HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.Public);
|
||||
HttpContext.Current.Response.Cache.SetMaxAge(TimeSpan.MaxValue);
|
||||
HttpContext.Current.Response.Cache.AddValidationCallback(new HttpCacheValidateHandler(this.CacheValidationCallback), this.startupTime);
|
||||
HttpContext.Current.Response.Cache.SetValidUntilExpires(true);
|
||||
}
|
||||
switch ((string)match.Data)
|
||||
{
|
||||
case HelpMethodName:
|
||||
return GetHelpPage();
|
||||
case HelpOperationMethodName:
|
||||
return GetOperationHelpPage(match.BoundVariables["operation"]);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
void CacheValidationCallback(HttpContext context, object state, ref HttpValidationStatus result)
|
||||
{
|
||||
if (((DateTime)state) == this.startupTime)
|
||||
{
|
||||
result = HttpValidationStatus.Valid;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = HttpValidationStatus.Invalid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class OperationHelpInformation
|
||||
{
|
||||
OperationDescription od;
|
||||
WebHttpBehavior behavior;
|
||||
MessageHelpInformation request;
|
||||
MessageHelpInformation response;
|
||||
|
||||
internal OperationHelpInformation(WebHttpBehavior behavior, OperationDescription od)
|
||||
{
|
||||
this.od = od;
|
||||
this.behavior = behavior;
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return od.Name;
|
||||
}
|
||||
}
|
||||
|
||||
public string UriTemplate
|
||||
{
|
||||
get
|
||||
{
|
||||
return UriTemplateClientFormatter.GetUTStringOrDefault(od);
|
||||
}
|
||||
}
|
||||
|
||||
public string Method
|
||||
{
|
||||
get
|
||||
{
|
||||
return WebHttpBehavior.GetWebMethod(od);
|
||||
}
|
||||
}
|
||||
|
||||
public string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
return WebHttpBehavior.GetDescription(od);
|
||||
}
|
||||
}
|
||||
|
||||
public string JavascriptCallbackParameterName
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.Response.SupportsJson && this.Method == WebHttpBehavior.GET)
|
||||
{
|
||||
return behavior.JavascriptCallbackParameterName;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public WebMessageBodyStyle BodyStyle
|
||||
{
|
||||
get
|
||||
{
|
||||
return behavior.GetBodyStyle(od);
|
||||
}
|
||||
}
|
||||
|
||||
public MessageHelpInformation Request
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.request == null)
|
||||
{
|
||||
this.request = new MessageHelpInformation(od, true, GetRequestBodyType(od, this.UriTemplate),
|
||||
this.BodyStyle == WebMessageBodyStyle.WrappedRequest || this.BodyStyle == WebMessageBodyStyle.Wrapped);
|
||||
}
|
||||
return this.request;
|
||||
}
|
||||
}
|
||||
|
||||
public MessageHelpInformation Response
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.response == null)
|
||||
{
|
||||
this.response = new MessageHelpInformation(od, false, GetResponseBodyType(od),
|
||||
this.BodyStyle == WebMessageBodyStyle.WrappedResponse || this.BodyStyle == WebMessageBodyStyle.Wrapped);
|
||||
}
|
||||
return this.response;
|
||||
}
|
||||
}
|
||||
|
||||
static Type GetResponseBodyType(OperationDescription od)
|
||||
{
|
||||
if (WebHttpBehavior.IsUntypedMessage(od.Messages[1]))
|
||||
{
|
||||
return typeof(Message);
|
||||
}
|
||||
else if (WebHttpBehavior.IsTypedMessage(od.Messages[1]))
|
||||
{
|
||||
return od.Messages[1].MessageType;
|
||||
}
|
||||
else if (od.Messages[1].Body.Parts.Count > 0)
|
||||
{
|
||||
// If it is more than 0 the response is wrapped and not supported
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (od.Messages[1].Body.ReturnValue.Type);
|
||||
}
|
||||
}
|
||||
|
||||
static Type GetRequestBodyType(OperationDescription od, string uriTemplate)
|
||||
{
|
||||
if (od.Behaviors.Contains(typeof(WebGetAttribute)))
|
||||
{
|
||||
return typeof(void);
|
||||
}
|
||||
else if (WebHttpBehavior.IsUntypedMessage(od.Messages[0]))
|
||||
{
|
||||
return typeof(Message);
|
||||
}
|
||||
else if (WebHttpBehavior.IsTypedMessage(od.Messages[0]))
|
||||
{
|
||||
return od.Messages[0].MessageType;
|
||||
}
|
||||
else
|
||||
{
|
||||
UriTemplate template = new UriTemplate(uriTemplate);
|
||||
IEnumerable<MessagePartDescription> parts =
|
||||
from part in od.Messages[0].Body.Parts
|
||||
where !template.PathSegmentVariableNames.Contains(part.Name.ToUpperInvariant()) && !template.QueryValueVariableNames.Contains(part.Name.ToUpperInvariant())
|
||||
select part;
|
||||
|
||||
if (parts.Count() == 1)
|
||||
{
|
||||
return parts.First().Type;
|
||||
}
|
||||
else if (parts.Count() == 0)
|
||||
{
|
||||
return typeof(void);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The request is wrapped and not supported
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MessageHelpInformation
|
||||
{
|
||||
public string BodyDescription { get; private set; }
|
||||
public string FormatString { get; private set; }
|
||||
public Type Type { get; private set; }
|
||||
public bool SupportsJson { get; private set; }
|
||||
public XmlSchemaSet SchemaSet { get; private set; }
|
||||
public XmlSchema Schema { get; private set; }
|
||||
public XElement XmlExample { get; private set; }
|
||||
public XElement JsonExample { get; private set; }
|
||||
|
||||
internal MessageHelpInformation(OperationDescription od, bool isRequest, Type type, bool wrapped)
|
||||
{
|
||||
this.Type = type;
|
||||
this.SupportsJson = WebHttpBehavior.SupportsJsonFormat(od);
|
||||
string direction = isRequest ? SR2.GetString(SR2.HelpPageRequest) : SR2.GetString(SR2.HelpPageResponse);
|
||||
|
||||
if (wrapped && !typeof(void).Equals(type))
|
||||
{
|
||||
this.BodyDescription = SR2.GetString(SR2.HelpPageBodyIsWrapped, direction);
|
||||
this.FormatString = SR2.GetString(SR2.HelpPageUnknown);
|
||||
}
|
||||
else if (typeof(void).Equals(type))
|
||||
{
|
||||
this.BodyDescription = SR2.GetString(SR2.HelpPageBodyIsEmpty, direction);
|
||||
this.FormatString = SR2.GetString(SR2.HelpPageNA);
|
||||
}
|
||||
else if (typeof(Message).IsAssignableFrom(type))
|
||||
{
|
||||
this.BodyDescription = SR2.GetString(SR2.HelpPageIsMessage, direction);
|
||||
this.FormatString = SR2.GetString(SR2.HelpPageUnknown);
|
||||
}
|
||||
else if (typeof(Stream).IsAssignableFrom(type))
|
||||
{
|
||||
this.BodyDescription = SR2.GetString(SR2.HelpPageIsStream, direction);
|
||||
this.FormatString = SR2.GetString(SR2.HelpPageUnknown);
|
||||
}
|
||||
else if (typeof(Atom10FeedFormatter).IsAssignableFrom(type))
|
||||
{
|
||||
this.BodyDescription = SR2.GetString(SR2.HelpPageIsAtom10Feed, direction);
|
||||
this.FormatString = WebMessageFormat.Xml.ToString();
|
||||
}
|
||||
else if (typeof(Atom10ItemFormatter).IsAssignableFrom(type))
|
||||
{
|
||||
this.BodyDescription = SR2.GetString(SR2.HelpPageIsAtom10Entry, direction);
|
||||
this.FormatString = WebMessageFormat.Xml.ToString();
|
||||
}
|
||||
else if (typeof(AtomPub10ServiceDocumentFormatter).IsAssignableFrom(type))
|
||||
{
|
||||
this.BodyDescription = SR2.GetString(SR2.HelpPageIsAtomPubServiceDocument, direction);
|
||||
this.FormatString = WebMessageFormat.Xml.ToString();
|
||||
}
|
||||
else if (typeof(AtomPub10CategoriesDocumentFormatter).IsAssignableFrom(type))
|
||||
{
|
||||
this.BodyDescription = SR2.GetString(SR2.HelpPageIsAtomPubCategoriesDocument, direction);
|
||||
this.FormatString = WebMessageFormat.Xml.ToString();
|
||||
}
|
||||
else if (typeof(Rss20FeedFormatter).IsAssignableFrom(type))
|
||||
{
|
||||
this.BodyDescription = SR2.GetString(SR2.HelpPageIsRSS20Feed, direction);
|
||||
this.FormatString = WebMessageFormat.Xml.ToString();
|
||||
}
|
||||
else if (typeof(SyndicationFeedFormatter).IsAssignableFrom(type))
|
||||
{
|
||||
this.BodyDescription = SR2.GetString(SR2.HelpPageIsSyndication, direction);
|
||||
this.FormatString = WebMessageFormat.Xml.ToString();
|
||||
}
|
||||
else if (typeof(XElement).IsAssignableFrom(type) || typeof(XmlElement).IsAssignableFrom(type))
|
||||
{
|
||||
this.BodyDescription = SR2.GetString(SR2.HelpPageIsXML, direction);
|
||||
this.FormatString = WebMessageFormat.Xml.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
bool usesXmlSerializer = od.Behaviors.Contains(typeof(XmlSerializerOperationBehavior));
|
||||
XmlQualifiedName name;
|
||||
this.SchemaSet = new XmlSchemaSet();
|
||||
IDictionary<XmlQualifiedName, Type> knownTypes = new Dictionary<XmlQualifiedName, Type>();
|
||||
if (usesXmlSerializer)
|
||||
{
|
||||
XmlReflectionImporter importer = new XmlReflectionImporter();
|
||||
XmlTypeMapping typeMapping = importer.ImportTypeMapping(this.Type);
|
||||
name = new XmlQualifiedName(typeMapping.ElementName, typeMapping.Namespace);
|
||||
XmlSchemas schemas = new XmlSchemas();
|
||||
XmlSchemaExporter exporter = new XmlSchemaExporter(schemas);
|
||||
exporter.ExportTypeMapping(typeMapping);
|
||||
foreach (XmlSchema schema in schemas)
|
||||
{
|
||||
this.SchemaSet.Add(schema);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
XsdDataContractExporter exporter = new XsdDataContractExporter();
|
||||
List<Type> listTypes = new List<Type>(od.KnownTypes);
|
||||
bool isQueryable;
|
||||
Type dataContractType = DataContractSerializerOperationFormatter.GetSubstituteDataContractType(this.Type, out isQueryable);
|
||||
listTypes.Add(dataContractType);
|
||||
exporter.Export(listTypes);
|
||||
if (!exporter.CanExport(dataContractType))
|
||||
{
|
||||
this.BodyDescription = SR2.GetString(SR2.HelpPageCouldNotGenerateSchema);
|
||||
this.FormatString = SR2.GetString(SR2.HelpPageUnknown);
|
||||
return;
|
||||
}
|
||||
name = exporter.GetRootElementName(dataContractType);
|
||||
DataContract typeDataContract = DataContract.GetDataContract(dataContractType);
|
||||
if (typeDataContract.KnownDataContracts != null)
|
||||
{
|
||||
foreach (XmlQualifiedName dataContractName in typeDataContract.KnownDataContracts.Keys)
|
||||
{
|
||||
knownTypes.Add(dataContractName, typeDataContract.KnownDataContracts[dataContractName].UnderlyingType);
|
||||
}
|
||||
}
|
||||
foreach (Type knownType in od.KnownTypes)
|
||||
{
|
||||
XmlQualifiedName knownTypeName = exporter.GetSchemaTypeName(knownType);
|
||||
if (!knownTypes.ContainsKey(knownTypeName))
|
||||
{
|
||||
knownTypes.Add(knownTypeName, knownType);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (XmlSchema schema in exporter.Schemas.Schemas())
|
||||
{
|
||||
this.SchemaSet.Add(schema);
|
||||
}
|
||||
}
|
||||
this.SchemaSet.Compile();
|
||||
|
||||
XmlWriterSettings settings = new XmlWriterSettings
|
||||
{
|
||||
CloseOutput = false,
|
||||
Indent = true,
|
||||
};
|
||||
|
||||
if (this.SupportsJson)
|
||||
{
|
||||
XDocument exampleDocument = new XDocument();
|
||||
using (XmlWriter writer = XmlWriter.Create(exampleDocument.CreateWriter(), settings))
|
||||
{
|
||||
HelpExampleGenerator.GenerateJsonSample(this.SchemaSet, name, writer, knownTypes);
|
||||
}
|
||||
this.JsonExample = exampleDocument.Root;
|
||||
}
|
||||
|
||||
if (name.Namespace != "http://schemas.microsoft.com/2003/10/Serialization/")
|
||||
{
|
||||
foreach (XmlSchema schema in this.SchemaSet.Schemas(name.Namespace))
|
||||
{
|
||||
this.Schema = schema;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
XDocument XmlExampleDocument = new XDocument();
|
||||
using (XmlWriter writer = XmlWriter.Create(XmlExampleDocument.CreateWriter(), settings))
|
||||
{
|
||||
HelpExampleGenerator.GenerateXmlSample(this.SchemaSet, name, writer);
|
||||
}
|
||||
this.XmlExample = XmlExampleDocument.Root;
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (Fx.IsFatal(e))
|
||||
{
|
||||
throw;
|
||||
}
|
||||
this.BodyDescription = SR2.GetString(SR2.HelpPageCouldNotGenerateSchema);
|
||||
this.FormatString = SR2.GetString(SR2.HelpPageUnknown);
|
||||
this.Schema = null;
|
||||
this.JsonExample = null;
|
||||
this.XmlExample = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,118 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
#pragma warning disable 1634 // Stops compiler from warning about unknown warnings (for Presharp)
|
||||
|
||||
namespace System.ServiceModel.Dispatcher
|
||||
{
|
||||
using System;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Description;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml;
|
||||
using System.Runtime.Serialization;
|
||||
using DiagnosticUtility = System.ServiceModel.DiagnosticUtility;
|
||||
using System.IO;
|
||||
using System.Collections.Specialized;
|
||||
using System.Net;
|
||||
|
||||
class HttpStreamFormatter : IDispatchMessageFormatter, IClientMessageFormatter
|
||||
{
|
||||
string contractName;
|
||||
string contractNs;
|
||||
string operationName;
|
||||
|
||||
public HttpStreamFormatter(OperationDescription operation)
|
||||
{
|
||||
if (operation == null)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("operation");
|
||||
}
|
||||
this.operationName = operation.Name;
|
||||
this.contractName = operation.DeclaringContract.Name;
|
||||
this.contractNs = operation.DeclaringContract.Namespace;
|
||||
}
|
||||
|
||||
public object DeserializeReply(Message message, object[] parameters)
|
||||
{
|
||||
return GetStreamFromMessage(message, false);
|
||||
}
|
||||
|
||||
public void DeserializeRequest(Message message, object[] parameters)
|
||||
{
|
||||
parameters[0] = GetStreamFromMessage(message, true);
|
||||
}
|
||||
|
||||
public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result)
|
||||
{
|
||||
Message message = CreateMessageFromStream(result);
|
||||
if (result == null)
|
||||
{
|
||||
SingleBodyParameterMessageFormatter.SuppressReplyEntityBody(message);
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
public Message SerializeRequest(MessageVersion messageVersion, object[] parameters)
|
||||
{
|
||||
Message message = CreateMessageFromStream(parameters[0]);
|
||||
if (parameters[0] == null)
|
||||
{
|
||||
SingleBodyParameterMessageFormatter.SuppressRequestEntityBody(message);
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
internal static bool IsEmptyMessage(Message message)
|
||||
{
|
||||
return message.IsEmpty;
|
||||
}
|
||||
|
||||
Message CreateMessageFromStream(object data)
|
||||
{
|
||||
Message result;
|
||||
if (data == null)
|
||||
{
|
||||
result = Message.CreateMessage(MessageVersion.None, (string) null);
|
||||
}
|
||||
else
|
||||
{
|
||||
Stream streamData = data as Stream;
|
||||
if (streamData == null)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR2.GetString(SR2.ParameterIsNotStreamType, data.GetType(), this.operationName, this.contractName, this.contractNs)));
|
||||
}
|
||||
result = ByteStreamMessage.CreateMessage(streamData);
|
||||
result.Properties[WebBodyFormatMessageProperty.Name] = WebBodyFormatMessageProperty.RawProperty;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Stream GetStreamFromMessage(Message message, bool isRequest)
|
||||
{
|
||||
object prop;
|
||||
message.Properties.TryGetValue(WebBodyFormatMessageProperty.Name, out prop);
|
||||
WebBodyFormatMessageProperty formatProperty = (prop as WebBodyFormatMessageProperty);
|
||||
if (formatProperty == null)
|
||||
{
|
||||
// GET and DELETE do not go through the encoder
|
||||
if (IsEmptyMessage(message))
|
||||
{
|
||||
return new MemoryStream();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR2.GetString(SR2.MessageFormatPropertyNotFound, this.operationName, this.contractName, this.contractNs)));
|
||||
}
|
||||
}
|
||||
if (formatProperty.Format != WebContentFormat.Raw)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR2.GetString(SR2.InvalidHttpMessageFormat, this.operationName, this.contractName, this.contractNs, formatProperty.Format, WebContentFormat.Raw)));
|
||||
}
|
||||
return new StreamFormatter.MessageBodyStream(message, null, null, HttpStreamMessage.StreamElementName, string.Empty, isRequest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,141 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
#pragma warning disable 1634, 1691
|
||||
namespace System.ServiceModel.Dispatcher
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Net;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Diagnostics;
|
||||
using System.ServiceModel.Web;
|
||||
using System.ServiceModel.Syndication;
|
||||
using System.Xml.Linq;
|
||||
using System.ServiceModel.Description;
|
||||
|
||||
internal class HttpUnhandledOperationInvoker : IOperationInvoker
|
||||
{
|
||||
const string HtmlContentType = "text/html; charset=UTF-8";
|
||||
|
||||
public bool IsSynchronous
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
public object[] AllocateInputs()
|
||||
{
|
||||
return new object[1];
|
||||
}
|
||||
|
||||
public Uri HelpUri { get; set; }
|
||||
|
||||
[SuppressMessage("Reliability", "Reliability104:CaughtAndHandledExceptionsRule", Justification = "The exception is thrown for tracing purposes")]
|
||||
public object Invoke(object instance, object[] inputs, out object[] outputs)
|
||||
{
|
||||
Message message = inputs[0] as Message;
|
||||
outputs = null;
|
||||
#pragma warning disable 56506 // [....], message.Properties is never null
|
||||
if (message == null)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
|
||||
SR2.GetString(SR2.HttpUnhandledOperationInvokerCalledWithoutMessage)));
|
||||
}
|
||||
// We might be here because we desire a redirect...
|
||||
Uri newLocation = null;
|
||||
Uri to = message.Headers.To;
|
||||
if (message.Properties.ContainsKey(WebHttpDispatchOperationSelector.RedirectPropertyName))
|
||||
{
|
||||
newLocation = message.Properties[WebHttpDispatchOperationSelector.RedirectPropertyName] as Uri;
|
||||
}
|
||||
if (newLocation != null && to != null)
|
||||
{
|
||||
// ...redirect
|
||||
Message redirectResult = WebOperationContext.Current.CreateStreamResponse(s => HelpHtmlBuilder.CreateTransferRedirectPage(to.AbsoluteUri, newLocation.AbsoluteUri).Save(s, SaveOptions.OmitDuplicateNamespaces), Atom10Constants.HtmlMediaType);
|
||||
WebOperationContext.Current.OutgoingResponse.Location = newLocation.AbsoluteUri;
|
||||
WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.TemporaryRedirect;
|
||||
WebOperationContext.Current.OutgoingResponse.ContentType = HtmlContentType;
|
||||
|
||||
// Note that no exception is thrown along this path, even if the debugger is attached
|
||||
if (DiagnosticUtility.ShouldTraceInformation)
|
||||
{
|
||||
TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.WebRequestRedirect,
|
||||
SR2.GetString(SR2.TraceCodeWebRequestRedirect, to, newLocation));
|
||||
}
|
||||
return redirectResult;
|
||||
}
|
||||
// otherwise we are here to issue either a 404 or a 405
|
||||
bool uriMatched = false;
|
||||
if (message.Properties.ContainsKey(WebHttpDispatchOperationSelector.HttpOperationSelectorUriMatchedPropertyName))
|
||||
{
|
||||
uriMatched = (bool) message.Properties[WebHttpDispatchOperationSelector.HttpOperationSelectorUriMatchedPropertyName];
|
||||
}
|
||||
#pragma warning enable 56506
|
||||
Message result = null;
|
||||
Uri helpUri = this.HelpUri != null ? UriTemplate.RewriteUri(this.HelpUri, WebOperationContext.Current.IncomingRequest.Headers[HttpRequestHeader.Host]) : null;
|
||||
if (uriMatched)
|
||||
{
|
||||
WebHttpDispatchOperationSelectorData allowedMethodsData = null;
|
||||
if (message.Properties.TryGetValue(WebHttpDispatchOperationSelector.HttpOperationSelectorDataPropertyName, out allowedMethodsData))
|
||||
{
|
||||
WebOperationContext.Current.OutgoingResponse.Headers[HttpResponseHeader.Allow] = allowedMethodsData.AllowHeader;
|
||||
}
|
||||
result = WebOperationContext.Current.CreateStreamResponse(s => HelpHtmlBuilder.CreateMethodNotAllowedPage(helpUri).Save(s, SaveOptions.OmitDuplicateNamespaces), Atom10Constants.HtmlMediaType);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = WebOperationContext.Current.CreateStreamResponse(s => HelpHtmlBuilder.CreateEndpointNotFound(helpUri).Save(s, SaveOptions.OmitDuplicateNamespaces), Atom10Constants.HtmlMediaType);
|
||||
|
||||
}
|
||||
WebOperationContext.Current.OutgoingResponse.StatusCode = uriMatched ? HttpStatusCode.MethodNotAllowed : HttpStatusCode.NotFound;
|
||||
WebOperationContext.Current.OutgoingResponse.ContentType = HtmlContentType;
|
||||
|
||||
try
|
||||
{
|
||||
if (!uriMatched)
|
||||
{
|
||||
if (Debugger.IsAttached)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR2.GetString(SR2.WebRequestDidNotMatchOperation,
|
||||
OperationContext.Current.IncomingMessageHeaders.To)));
|
||||
}
|
||||
else
|
||||
{
|
||||
DiagnosticUtility.TraceHandledException(new InvalidOperationException(SR2.GetString(SR2.WebRequestDidNotMatchOperation,
|
||||
OperationContext.Current.IncomingMessageHeaders.To)), TraceEventType.Warning);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Debugger.IsAttached)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR2.GetString(SR2.WebRequestDidNotMatchMethod,
|
||||
WebOperationContext.Current.IncomingRequest.Method, OperationContext.Current.IncomingMessageHeaders.To)));
|
||||
}
|
||||
else
|
||||
{
|
||||
DiagnosticUtility.TraceHandledException(new InvalidOperationException(SR2.GetString(SR2.WebRequestDidNotMatchMethod,
|
||||
WebOperationContext.Current.IncomingRequest.Method, OperationContext.Current.IncomingMessageHeaders.To)), TraceEventType.Warning);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
// catch the exception - its only used for tracing
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
|
||||
}
|
||||
|
||||
public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,86 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
#pragma warning disable 1634, 1691
|
||||
namespace System.ServiceModel.Dispatcher
|
||||
{
|
||||
using System.Net;
|
||||
using System.Linq;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Web;
|
||||
using System.Web;
|
||||
using System.ServiceModel.Description;
|
||||
using System.Diagnostics;
|
||||
using System.ServiceModel.Diagnostics;
|
||||
|
||||
class JavascriptCallbackMessageInspector : IDispatchMessageInspector
|
||||
{
|
||||
internal static readonly string applicationJavaScriptMediaType = "application/x-javascript";
|
||||
|
||||
public JavascriptCallbackMessageInspector(string callbackParameterName)
|
||||
{
|
||||
this.CallbackParameterName = callbackParameterName;
|
||||
if (DiagnosticUtility.ShouldTraceInformation)
|
||||
{
|
||||
TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.JsonpCallbackNameSet, SR2.GetString(SR2.TraceCodeJsonpCallbackNameSet, callbackParameterName));
|
||||
}
|
||||
}
|
||||
|
||||
string CallbackParameterName { get; set; }
|
||||
|
||||
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
|
||||
{
|
||||
if (HttpContext.Current != null &&
|
||||
HttpContext.Current.User != null &&
|
||||
HttpContext.Current.User.Identity != null &&
|
||||
HttpContext.Current.User.Identity.IsAuthenticated)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR2.CrossDomainJavascriptAuthNotSupported));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void BeforeSendReply(ref Message reply, object correlationState)
|
||||
{
|
||||
WebBodyFormatMessageProperty formatProperty;
|
||||
JavascriptCallbackResponseMessageProperty javascriptCallbackResponseMessageProperty = null;
|
||||
if (reply.Properties.TryGetValue<WebBodyFormatMessageProperty>(WebBodyFormatMessageProperty.Name, out formatProperty) &&
|
||||
formatProperty != null &&
|
||||
formatProperty.Format == WebContentFormat.Json)
|
||||
{
|
||||
if (!reply.Properties.TryGetValue<JavascriptCallbackResponseMessageProperty>(JavascriptCallbackResponseMessageProperty.Name, out javascriptCallbackResponseMessageProperty)
|
||||
|| javascriptCallbackResponseMessageProperty == null)
|
||||
{
|
||||
javascriptCallbackResponseMessageProperty = WebHttpBehavior.TrySetupJavascriptCallback(this.CallbackParameterName);
|
||||
if (javascriptCallbackResponseMessageProperty != null)
|
||||
{
|
||||
reply.Properties.Add(JavascriptCallbackResponseMessageProperty.Name, javascriptCallbackResponseMessageProperty);
|
||||
}
|
||||
}
|
||||
if (javascriptCallbackResponseMessageProperty != null)
|
||||
{
|
||||
HttpResponseMessageProperty property;
|
||||
if (reply.Properties.TryGetValue<HttpResponseMessageProperty>(HttpResponseMessageProperty.Name, out property) &&
|
||||
property != null)
|
||||
{
|
||||
property.Headers[HttpResponseHeader.ContentType] = applicationJavaScriptMediaType;
|
||||
if (javascriptCallbackResponseMessageProperty.StatusCode == null)
|
||||
{
|
||||
javascriptCallbackResponseMessageProperty.StatusCode = property.StatusCode;
|
||||
}
|
||||
property.StatusCode = HttpStatusCode.OK;
|
||||
|
||||
if (property.SuppressEntityBody)
|
||||
{
|
||||
property.SuppressEntityBody = false;
|
||||
Message nullJsonMessage = WebOperationContext.Current.CreateJsonResponse<object>(null);
|
||||
nullJsonMessage.Properties.CopyProperties(reply.Properties);
|
||||
reply = nullJsonMessage;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
namespace System.ServiceModel.Dispatcher
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.Serialization.Json;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Web;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
|
||||
class JsonFormatMapping : MultiplexingFormatMapping
|
||||
{
|
||||
public static readonly WebContentFormat WebContentFormat = WebContentFormat.Json;
|
||||
|
||||
static readonly string defaultMediaType = JsonGlobals.applicationJsonMediaType;
|
||||
static Dictionary<Encoding, MessageEncoder> encoders = new Dictionary<Encoding, MessageEncoder>();
|
||||
static object thisLock = new object();
|
||||
|
||||
public JsonFormatMapping(Encoding writeEncoding, WebContentTypeMapper contentTypeMapper)
|
||||
: base(writeEncoding, contentTypeMapper)
|
||||
{ }
|
||||
|
||||
public override WebContentFormat ContentFormat
|
||||
{
|
||||
get { return JsonFormatMapping.WebContentFormat; }
|
||||
}
|
||||
|
||||
public override WebMessageFormat MessageFormat
|
||||
{
|
||||
get { return WebMessageFormat.Json; }
|
||||
}
|
||||
|
||||
public override string DefaultMediaType
|
||||
{
|
||||
get { return JsonFormatMapping.defaultMediaType; }
|
||||
}
|
||||
|
||||
protected override MessageEncoder Encoder
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (thisLock)
|
||||
{
|
||||
if (!JsonFormatMapping.encoders.ContainsKey(this.writeEncoding))
|
||||
{
|
||||
JsonFormatMapping.encoders[this.writeEncoding] = new JsonMessageEncoderFactory(this.writeEncoding, 0, 0, new XmlDictionaryReaderQuotas(), false).Encoder;
|
||||
}
|
||||
}
|
||||
return JsonFormatMapping.encoders[this.writeEncoding];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,221 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
#pragma warning disable 1634, 1691
|
||||
namespace System.ServiceModel.Dispatcher
|
||||
{
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Specialized;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Description;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
using System.Xml;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Runtime.Serialization.Json;
|
||||
|
||||
public class JsonQueryStringConverter : QueryStringConverter
|
||||
{
|
||||
DataContractSerializerOperationBehavior dataContractSerializerOperationBehavior = null;
|
||||
OperationDescription operationDescription = null;
|
||||
|
||||
|
||||
public JsonQueryStringConverter() : base()
|
||||
{
|
||||
}
|
||||
|
||||
internal JsonQueryStringConverter(OperationDescription operationDescription)
|
||||
: base()
|
||||
{
|
||||
if (operationDescription == null)
|
||||
{
|
||||
throw System.ServiceModel.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("operationDescription");
|
||||
}
|
||||
this.operationDescription = operationDescription;
|
||||
this.dataContractSerializerOperationBehavior = this.operationDescription.Behaviors.Find<DataContractSerializerOperationBehavior>();
|
||||
}
|
||||
|
||||
public override bool CanConvert(Type type)
|
||||
{
|
||||
XsdDataContractExporter exporter = new XsdDataContractExporter();
|
||||
return exporter.CanExport(type);
|
||||
}
|
||||
|
||||
public override object ConvertStringToValue(string parameter, Type parameterType)
|
||||
{
|
||||
if (parameterType == null)
|
||||
{
|
||||
throw System.ServiceModel.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("parameterType");
|
||||
}
|
||||
switch (Type.GetTypeCode(parameterType))
|
||||
{
|
||||
case TypeCode.Byte:
|
||||
case TypeCode.SByte:
|
||||
case TypeCode.Int16:
|
||||
case TypeCode.Int32:
|
||||
case TypeCode.Int64:
|
||||
case TypeCode.UInt16:
|
||||
case TypeCode.UInt32:
|
||||
case TypeCode.UInt64:
|
||||
case TypeCode.Single:
|
||||
case TypeCode.Double:
|
||||
case TypeCode.Decimal:
|
||||
case TypeCode.Boolean:
|
||||
// base.ConvertStringToValue handles parameter == null case.
|
||||
return base.ConvertStringToValue(parameter, parameterType);
|
||||
case TypeCode.Char:
|
||||
case TypeCode.String:
|
||||
case TypeCode.DateTime:
|
||||
// base.ConvertStringToValue handles parameter == null case.
|
||||
// IsFirstCharacterReservedCharacter returns false for null strings.
|
||||
if (IsFirstCharacterReservedCharacter(parameter, '"'))
|
||||
{
|
||||
return CreateJsonDeserializedObject(parameter.Trim(), parameterType);
|
||||
}
|
||||
return base.ConvertStringToValue(parameter, parameterType);
|
||||
default:
|
||||
{
|
||||
if (parameterType == typeof(Guid))
|
||||
{
|
||||
if (parameter == null)
|
||||
{
|
||||
return default(Guid);
|
||||
}
|
||||
if (IsFirstCharacterReservedCharacter(parameter, '"'))
|
||||
{
|
||||
return CreateJsonDeserializedObject(parameter.Trim(), parameterType);
|
||||
}
|
||||
return base.ConvertStringToValue(parameter, parameterType);
|
||||
}
|
||||
else if (parameterType == typeof(Uri))
|
||||
{
|
||||
if (parameter == null)
|
||||
{
|
||||
return default(Uri);
|
||||
}
|
||||
if (IsFirstCharacterReservedCharacter(parameter, '"'))
|
||||
{
|
||||
return CreateJsonDeserializedObject(parameter.Trim(), parameterType);
|
||||
}
|
||||
return base.ConvertStringToValue(parameter, parameterType);
|
||||
}
|
||||
else if (parameterType == typeof(TimeSpan))
|
||||
{
|
||||
if (parameter == null)
|
||||
{
|
||||
return default(TimeSpan);
|
||||
}
|
||||
if (IsFirstCharacterReservedCharacter(parameter, '"'))
|
||||
{
|
||||
return CreateJsonDeserializedObject(parameter.Trim(), parameterType);
|
||||
}
|
||||
return base.ConvertStringToValue(parameter, parameterType);
|
||||
}
|
||||
else if (parameterType == typeof(byte[]))
|
||||
{
|
||||
if (parameter == null)
|
||||
{
|
||||
return default(byte[]);
|
||||
}
|
||||
if (IsFirstCharacterReservedCharacter(parameter, '['))
|
||||
{
|
||||
return CreateJsonDeserializedObject(parameter.Trim(), parameterType);
|
||||
}
|
||||
return base.ConvertStringToValue(parameter, parameterType);
|
||||
}
|
||||
else if (parameterType == typeof(DateTimeOffset))
|
||||
{
|
||||
if (parameter == null)
|
||||
{
|
||||
return default(DateTimeOffset);
|
||||
}
|
||||
if (IsFirstCharacterReservedCharacter(parameter, '{'))
|
||||
{
|
||||
return CreateJsonDeserializedObject(parameter.Trim(), parameterType);
|
||||
}
|
||||
return base.ConvertStringToValue(parameter, parameterType);
|
||||
}
|
||||
else if (parameterType == typeof(object))
|
||||
{
|
||||
if (parameter == null)
|
||||
{
|
||||
return default(object);
|
||||
}
|
||||
if (IsFirstCharacterReservedCharacter(parameter, '{'))
|
||||
{
|
||||
return CreateJsonDeserializedObject(parameter.Trim(), parameterType);
|
||||
}
|
||||
return base.ConvertStringToValue(parameter, parameterType);
|
||||
}
|
||||
|
||||
if (parameter == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return CreateJsonDeserializedObject(parameter.Trim(), parameterType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override string ConvertValueToString(object parameter, Type parameterType)
|
||||
{
|
||||
if (parameter == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
MemoryStream memoryStream = new MemoryStream();
|
||||
XmlDictionaryWriter jsonWriter = JsonReaderWriterFactory.CreateJsonWriter(memoryStream, Encoding.UTF8);
|
||||
GetDataContractJsonSerializer(parameterType).WriteObject(jsonWriter, parameter);
|
||||
jsonWriter.Flush();
|
||||
memoryStream.Seek(0, SeekOrigin.Begin);
|
||||
return Encoding.UTF8.GetString(memoryStream.GetBuffer(), (int) memoryStream.Position, (int) memoryStream.Length);
|
||||
}
|
||||
|
||||
object CreateJsonDeserializedObject(string parameter, Type parameterType)
|
||||
{
|
||||
byte[] byteArray = Encoding.UTF8.GetBytes(parameter);
|
||||
XmlDictionaryReader jsonReader = JsonReaderWriterFactory.CreateJsonReader
|
||||
(byteArray, 0, byteArray.Length, Encoding.UTF8, XmlDictionaryReaderQuotas.Max, null);
|
||||
return GetDataContractJsonSerializer(parameterType).ReadObject(jsonReader);
|
||||
}
|
||||
|
||||
DataContractJsonSerializer GetDataContractJsonSerializer(Type parameterType)
|
||||
{
|
||||
if (this.operationDescription == null)
|
||||
{
|
||||
return new DataContractJsonSerializer(parameterType);
|
||||
}
|
||||
else if (this.dataContractSerializerOperationBehavior == null)
|
||||
{
|
||||
return new DataContractJsonSerializer(parameterType, operationDescription.KnownTypes);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new DataContractJsonSerializer(parameterType, this.operationDescription.KnownTypes, this.dataContractSerializerOperationBehavior.maxItemsInObjectGraph,
|
||||
this.dataContractSerializerOperationBehavior.IgnoreExtensionDataObject, this.dataContractSerializerOperationBehavior.DataContractSurrogate, false); //alwaysEmitTypeInformation
|
||||
}
|
||||
}
|
||||
|
||||
bool IsFirstCharacterReservedCharacter(string parameter, char reservedCharacter)
|
||||
{
|
||||
if (parameter == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
string localParameter = parameter.Trim();
|
||||
if (localParameter == string.Empty)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (localParameter[0] == reservedCharacter)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,119 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
namespace System.ServiceModel.Dispatcher
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Mime;
|
||||
using System.Runtime;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Description;
|
||||
using System.ServiceModel.Web;
|
||||
|
||||
class MultiplexingDispatchMessageFormatter : IDispatchMessageFormatter
|
||||
{
|
||||
Dictionary<WebMessageFormat, IDispatchMessageFormatter> formatters;
|
||||
WebMessageFormat defaultFormat;
|
||||
Dictionary<WebMessageFormat, string> defaultContentTypes;
|
||||
|
||||
public WebMessageFormat DefaultFormat
|
||||
{
|
||||
get { return this.defaultFormat; }
|
||||
}
|
||||
|
||||
public Dictionary<WebMessageFormat, string> DefaultContentTypes
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.defaultContentTypes;
|
||||
}
|
||||
}
|
||||
|
||||
public MultiplexingDispatchMessageFormatter(Dictionary<WebMessageFormat, IDispatchMessageFormatter> formatters, WebMessageFormat defaultFormat)
|
||||
{
|
||||
if (formatters == null)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("formatters");
|
||||
}
|
||||
this.formatters = formatters;
|
||||
this.defaultFormat = defaultFormat;
|
||||
this.defaultContentTypes = new Dictionary<WebMessageFormat, string>();
|
||||
Fx.Assert(this.formatters.ContainsKey(this.defaultFormat), "The default format should always be included in the dictionary of formatters.");
|
||||
}
|
||||
|
||||
public void DeserializeRequest(Message message, object[] parameters)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR2.GetString(SR2.SerializingRequestNotSupportedByFormatter, this)));
|
||||
}
|
||||
|
||||
public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result)
|
||||
{
|
||||
WebOperationContext currentContext = WebOperationContext.Current;
|
||||
OutgoingWebResponseContext outgoingResponse = null;
|
||||
|
||||
if (currentContext != null)
|
||||
{
|
||||
outgoingResponse = currentContext.OutgoingResponse;
|
||||
}
|
||||
|
||||
WebMessageFormat format = this.defaultFormat;
|
||||
if (outgoingResponse != null)
|
||||
{
|
||||
WebMessageFormat? nullableFormat = outgoingResponse.Format;
|
||||
if (nullableFormat.HasValue)
|
||||
{
|
||||
format = nullableFormat.Value;
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.formatters.ContainsKey(format))
|
||||
{
|
||||
string operationName = "<null>";
|
||||
|
||||
if (OperationContext.Current != null)
|
||||
{
|
||||
MessageProperties messageProperties = OperationContext.Current.IncomingMessageProperties;
|
||||
if (messageProperties.ContainsKey(WebHttpDispatchOperationSelector.HttpOperationNamePropertyName))
|
||||
{
|
||||
operationName = messageProperties[WebHttpDispatchOperationSelector.HttpOperationNamePropertyName] as string;
|
||||
}
|
||||
}
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR2.GetString(SR2.OperationDoesNotSupportFormat, operationName, format.ToString())));
|
||||
}
|
||||
|
||||
if (outgoingResponse != null && string.IsNullOrEmpty(outgoingResponse.ContentType))
|
||||
{
|
||||
string automatedSelectionContentType = outgoingResponse.AutomatedFormatSelectionContentType;
|
||||
if (!string.IsNullOrEmpty(automatedSelectionContentType))
|
||||
{
|
||||
// Don't set the content-type if it is default xml for backwards compatiabilty
|
||||
if (!string.Equals(automatedSelectionContentType, defaultContentTypes[WebMessageFormat.Xml], StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
outgoingResponse.ContentType = automatedSelectionContentType;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Don't set the content-type if it is default xml for backwards compatiabilty
|
||||
if (format != WebMessageFormat.Xml)
|
||||
{
|
||||
outgoingResponse.ContentType = defaultContentTypes[format];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Message message = this.formatters[format].SerializeReply(messageVersion, parameters, result);
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
public bool SupportsMessageFormat(WebMessageFormat format)
|
||||
{
|
||||
return this.formatters.ContainsKey(format);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,83 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
namespace System.ServiceModel.Dispatcher
|
||||
{
|
||||
using System.Net.Mime;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Web;
|
||||
using System.Text;
|
||||
|
||||
abstract class MultiplexingFormatMapping
|
||||
{
|
||||
protected Encoding writeEncoding;
|
||||
protected string writeCharset;
|
||||
protected WebContentTypeMapper contentTypeMapper;
|
||||
|
||||
abstract public WebMessageFormat MessageFormat { get; }
|
||||
abstract public WebContentFormat ContentFormat { get; }
|
||||
abstract public string DefaultMediaType { get; }
|
||||
abstract protected MessageEncoder Encoder { get; }
|
||||
|
||||
ContentType defaultContentType;
|
||||
|
||||
public ContentType DefaultContentType
|
||||
{
|
||||
get
|
||||
{
|
||||
if (defaultContentType == null)
|
||||
{
|
||||
defaultContentType = new ContentType(this.DefaultMediaType) { CharSet = this.writeCharset };
|
||||
}
|
||||
return defaultContentType;
|
||||
}
|
||||
}
|
||||
|
||||
public MultiplexingFormatMapping(Encoding writeEncoding, WebContentTypeMapper contentTypeMapper)
|
||||
{
|
||||
if (writeEncoding == null)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writeEncoding");
|
||||
}
|
||||
this.writeEncoding = writeEncoding;
|
||||
this.writeCharset = TextEncoderDefaults.EncodingToCharSet(writeEncoding);
|
||||
this.contentTypeMapper = contentTypeMapper;
|
||||
}
|
||||
|
||||
public bool CanFormatResponse(ContentType acceptHeaderElement, bool matchCharset, out ContentType contentType)
|
||||
{
|
||||
if (acceptHeaderElement == null)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("acceptHeaderElement");
|
||||
}
|
||||
|
||||
// Scrub the content type so that it is only mediaType and the charset
|
||||
string charset = acceptHeaderElement.CharSet;
|
||||
contentType = new ContentType(acceptHeaderElement.MediaType);
|
||||
contentType.CharSet = this.DefaultContentType.CharSet;
|
||||
string contentTypeStr = contentType.ToString();
|
||||
|
||||
if (matchCharset &&
|
||||
!string.IsNullOrEmpty(charset) &&
|
||||
!string.Equals(charset, this.DefaultContentType.CharSet, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.contentTypeMapper != null &&
|
||||
this.contentTypeMapper.GetMessageFormatForContentType(contentType.MediaType) == this.ContentFormat)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.Encoder.IsContentTypeSupported(contentTypeStr) &&
|
||||
(charset == null || contentType.CharSet == this.DefaultContentType.CharSet))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
contentType = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
namespace System.ServiceModel.Dispatcher
|
||||
{
|
||||
class NameValueCache<T>
|
||||
{
|
||||
// The NameValueCache implements a structure that uses a dictionary to map objects to
|
||||
// indices of an array of cache entries. This allows us to store the cache entries in
|
||||
// the order in which they were added to the cache, and yet still lookup any cache entry.
|
||||
// The eviction policy of the cache is to evict the least-recently-added cache entry.
|
||||
// Using a pointer to the next available cache entry in the array, we can always be sure
|
||||
// that the given entry is the oldest entry.
|
||||
Hashtable cache;
|
||||
string[] currentKeys;
|
||||
int nextAvailableCacheIndex;
|
||||
object cachelock;
|
||||
internal const int maxNumberofEntriesInCache = 16;
|
||||
|
||||
public NameValueCache()
|
||||
: this(maxNumberofEntriesInCache)
|
||||
{
|
||||
}
|
||||
|
||||
public NameValueCache(int maxCacheEntries)
|
||||
{
|
||||
cache = new Hashtable();
|
||||
currentKeys = new string[maxCacheEntries];
|
||||
cachelock = new object();
|
||||
}
|
||||
|
||||
public T Lookup(string key)
|
||||
{
|
||||
return (T)cache[key];
|
||||
}
|
||||
|
||||
public void AddOrUpdate(string key, T value)
|
||||
{
|
||||
lock (cache)
|
||||
{
|
||||
if (!cache.ContainsKey(key))
|
||||
{
|
||||
if (!String.IsNullOrEmpty(currentKeys[nextAvailableCacheIndex]))
|
||||
{
|
||||
cache.Remove(currentKeys[nextAvailableCacheIndex]);
|
||||
}
|
||||
currentKeys[nextAvailableCacheIndex] = key;
|
||||
nextAvailableCacheIndex = ++nextAvailableCacheIndex % currentKeys.Length;
|
||||
}
|
||||
cache[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user