Imported Upstream version 3.6.0

Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
This commit is contained in:
Jo Shields
2014-08-13 10:39:27 +01:00
commit a575963da9
50588 changed files with 8155799 additions and 0 deletions

View File

@ -0,0 +1,222 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Web.Http.SelfHost.ServiceModel;
using System.Web.Http.SelfHost.ServiceModel.Channels;
namespace System.Web.Http.SelfHost.Channels
{
/// <summary>
/// A binding used with endpoints for web services that use strongly-type HTTP request
/// and response messages.
/// </summary>
public class HttpBinding : Binding, IBindingRuntimePreferences
{
internal const string CollectionElementName = "httpBinding";
internal const TransferMode DefaultTransferMode = System.ServiceModel.TransferMode.Buffered;
private HttpsTransportBindingElement _httpsTransportBindingElement;
private HttpTransportBindingElement _httpTransportBindingElement;
private HttpBindingSecurity _security;
private HttpMessageEncodingBindingElement _httpMessageEncodingBindingElement;
/// <summary>
/// Initializes a new instance of the <see cref="HttpBinding"/> class.
/// </summary>
public HttpBinding()
{
Initialize();
}
/// <summary>
/// Initializes a new instance of the <see cref="HttpBinding"/> class with the
/// type of security used by the binding explicitly specified.
/// </summary>
/// <param name="securityMode">The value of <see cref="HttpBindingSecurityMode"/> that
/// specifies the type of security that is used to configure a service endpoint using the
/// <see cref="HttpBinding"/> binding.
/// </param>
public HttpBinding(HttpBindingSecurityMode securityMode)
: this()
{
_security.Mode = securityMode;
}
/// <summary>
/// Gets the envelope version that is used by endpoints that are configured to use an
/// <see cref="HttpBinding"/> binding. Always returns <see cref="System.ServiceModel.EnvelopeVersion.None"/>.
/// </summary>
[SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification = "This is existing public API")]
public EnvelopeVersion EnvelopeVersion
{
get { return EnvelopeVersion.None; }
}
/// <summary>
/// Gets or sets a value that indicates whether the hostname is used to reach the
/// service when matching the URI.
/// </summary>
[DefaultValue(HttpTransportDefaults.HostNameComparisonMode)]
public HostNameComparisonMode HostNameComparisonMode
{
get { return _httpTransportBindingElement.HostNameComparisonMode; }
set
{
_httpTransportBindingElement.HostNameComparisonMode = value;
_httpsTransportBindingElement.HostNameComparisonMode = value;
}
}
/// <summary>
/// Gets or sets the maximum amount of memory allocated for the buffer manager that manages the buffers
/// required by endpoints that use this binding.
/// </summary>
[DefaultValue(TransportDefaults.MaxBufferPoolSize)]
public long MaxBufferPoolSize
{
get { return _httpTransportBindingElement.MaxBufferPoolSize; }
set
{
_httpTransportBindingElement.MaxBufferPoolSize = value;
_httpsTransportBindingElement.MaxBufferPoolSize = value;
}
}
/// <summary>
/// Gets or sets the maximum amount of memory that is allocated for use by the manager of the message
/// buffers that receive messages from the channel.
/// </summary>
[DefaultValue(TransportDefaults.MaxBufferSize)]
public int MaxBufferSize
{
get { return _httpTransportBindingElement.MaxBufferSize; }
set
{
_httpTransportBindingElement.MaxBufferSize = value;
_httpsTransportBindingElement.MaxBufferSize = value;
}
}
/// <summary>
/// Gets or sets the maximum size for a message that can be processed by the binding.
/// </summary>
[DefaultValue(TransportDefaults.MaxReceivedMessageSize)]
public long MaxReceivedMessageSize
{
get { return _httpTransportBindingElement.MaxReceivedMessageSize; }
set
{
_httpTransportBindingElement.MaxReceivedMessageSize = value;
_httpsTransportBindingElement.MaxReceivedMessageSize = value;
}
}
/// <summary>
/// Gets the URI transport scheme for the channels and listeners that are configured
/// with this binding. (Overrides <see cref="System.ServiceModel.Channels.Binding.Scheme">
/// Binding.Scheme</see>.)
/// </summary>
public override string Scheme
{
get { return GetTransport().Scheme; }
}
/// <summary>
/// Gets or sets the security settings used with this binding.
/// </summary>
public HttpBindingSecurity Security
{
get { return _security; }
set
{
if (value == null)
{
throw Error.ArgumentNull("value");
}
_security = value;
}
}
/// <summary>
/// Gets or sets a value that indicates whether the service configured with the
/// binding uses streamed or buffered (or both) modes of message transfer.
/// </summary>
[DefaultValue(HttpTransportDefaults.TransferMode)]
public TransferMode TransferMode
{
get { return _httpTransportBindingElement.TransferMode; }
set
{
_httpTransportBindingElement.TransferMode = value;
_httpsTransportBindingElement.TransferMode = value;
}
}
/// <summary>
/// Gets a value indicating whether incoming requests can be handled more efficiently synchronously or asynchronously.
/// </summary>
[SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Justification = "This is the pattern used by all standard bindings.")]
bool IBindingRuntimePreferences.ReceiveSynchronously
{
get { return false; }
}
/// <summary>
/// Returns an ordered collection of binding elements contained in the current binding.
/// (Overrides <see cref="System.ServiceModel.Channels.Binding.CreateBindingElements">
/// Binding.CreateBindingElements</see>.)
/// </summary>
/// <returns>
/// An ordered collection of binding elements contained in the current binding.
/// </returns>
public override BindingElementCollection CreateBindingElements()
{
BindingElementCollection bindingElements = new BindingElementCollection();
bindingElements.Add(_httpMessageEncodingBindingElement);
bindingElements.Add(GetTransport());
return bindingElements.Clone();
}
private TransportBindingElement GetTransport()
{
if (_security.Mode == HttpBindingSecurityMode.Transport)
{
_security.Transport.ConfigureTransportProtectionAndAuthentication(_httpsTransportBindingElement);
return _httpsTransportBindingElement;
}
else if (_security.Mode == HttpBindingSecurityMode.TransportCredentialOnly)
{
_security.Transport.ConfigureTransportAuthentication(_httpTransportBindingElement);
return _httpTransportBindingElement;
}
_security.Transport.DisableTransportAuthentication(_httpTransportBindingElement);
return _httpTransportBindingElement;
}
private void Initialize()
{
_security = new HttpBindingSecurity();
_httpTransportBindingElement = new HttpTransportBindingElement();
_httpTransportBindingElement.ManualAddressing = true;
_httpsTransportBindingElement = new HttpsTransportBindingElement();
_httpsTransportBindingElement.ManualAddressing = true;
_httpMessageEncodingBindingElement = new HttpMessageEncodingBindingElement();
}
}
}

View File

@ -0,0 +1,56 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.ServiceModel;
namespace System.Web.Http.SelfHost.Channels
{
/// <summary>
/// Specifies the types of security available to a service endpoint configured to use an
/// <see cref="HttpBinding"/> binding.
/// </summary>
public sealed class HttpBindingSecurity
{
internal const HttpBindingSecurityMode DefaultMode = HttpBindingSecurityMode.None;
private HttpBindingSecurityMode _mode;
private HttpTransportSecurity _transportSecurity;
/// <summary>
/// Creates a new instance of the <see cref="HttpBindingSecurity"/> class.
/// </summary>
public HttpBindingSecurity()
{
_mode = DefaultMode;
_transportSecurity = new HttpTransportSecurity();
}
/// <summary>
/// Gets or sets the mode of security that is used by an endpoint configured to use an
/// <see cref="HttpBinding"/> binding.
/// </summary>
public HttpBindingSecurityMode Mode
{
get { return _mode; }
set
{
HttpBindingSecurityModeHelper.Validate(value, "value");
IsModeSet = true;
_mode = value;
}
}
/// <summary>
/// Gets or sets an object that contains the transport-level security settings for the
/// <see cref="HttpBinding"/> binding.
/// </summary>
public HttpTransportSecurity Transport
{
get { return _transportSecurity; }
set { _transportSecurity = value ?? new HttpTransportSecurity(); }
}
internal bool IsModeSet { get; private set; }
}
}

View File

@ -0,0 +1,26 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
namespace System.Web.Http.SelfHost.Channels
{
/// <summary>
/// Defines the modes of security that can be used to configure a service endpoint that uses the
/// <see cref="HttpBinding"/>.
/// </summary>
public enum HttpBindingSecurityMode
{
/// <summary>
/// Indicates no security is used with HTTP requests.
/// </summary>
None,
/// <summary>
/// Indicates that transport-level security is used with HTTP requests.
/// </summary>
Transport,
/// <summary>
/// Indicates that only HTTP-based client authentication is provided.
/// </summary>
TransportCredentialOnly,
}
}

View File

@ -0,0 +1,41 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.ComponentModel;
namespace System.Web.Http.SelfHost.Channels
{
/// <summary>
/// Internal helper class to validate <see cref="HttpBindingSecurityMode"/> enum values.
/// </summary>
internal static class HttpBindingSecurityModeHelper
{
private static readonly Type _httpBindingSecurityMode = typeof(HttpBindingSecurityMode);
/// <summary>
/// Determines whether the specified <paramref name="value"/> is defined by the <see cref="HttpBindingSecurityMode"/>
/// enumeration.
/// </summary>
/// <param name="value">The value to test.</param>
/// <returns><c>true</c> if <paramref name="value"/> is a valid <see cref="HttpBindingSecurityMode"/> value; otherwise<c> false</c>.</returns>
public static bool IsDefined(HttpBindingSecurityMode value)
{
return value == HttpBindingSecurityMode.None ||
value == HttpBindingSecurityMode.Transport ||
value == HttpBindingSecurityMode.TransportCredentialOnly;
}
/// <summary>
/// Validates the specified <paramref name="value"/> and throws an <see cref="InvalidEnumArgumentException"/>
/// exception if not valid.
/// </summary>
/// <param name="value">The value to validate.</param>
/// <param name="parameterName">Name of the parameter to use if throwing exception.</param>
public static void Validate(HttpBindingSecurityMode value, string parameterName)
{
if (!IsDefined(value))
{
throw Error.InvalidEnumArgument(parameterName, (int)value, _httpBindingSecurityMode);
}
}
}
}

View File

@ -0,0 +1,229 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Diagnostics.Contracts;
using System.Net.Http;
using System.ServiceModel.Channels;
using System.Web.Http.SelfHost.Properties;
using System.Xml;
namespace System.Web.Http.SelfHost.Channels
{
internal sealed class HttpMessage : Message
{
private HttpRequestMessage _request;
private HttpResponseMessage _response;
private MessageHeaders _headers;
private MessageProperties _properties;
public HttpMessage(HttpRequestMessage request)
{
Contract.Assert(request != null, "The 'request' parameter should not be null.");
_request = request;
Headers.To = request.RequestUri;
IsRequest = true;
}
public HttpMessage(HttpResponseMessage response)
{
Contract.Assert(response != null, "The 'response' parameter should not be null.");
_response = response;
IsRequest = false;
}
public override MessageVersion Version
{
get
{
EnsureNotDisposed();
return MessageVersion.None;
}
}
public override MessageHeaders Headers
{
get
{
EnsureNotDisposed();
if (_headers == null)
{
_headers = new MessageHeaders(MessageVersion.None);
}
return _headers;
}
}
public override MessageProperties Properties
{
get
{
EnsureNotDisposed();
if (_properties == null)
{
_properties = new MessageProperties();
_properties.AllowOutputBatching = false;
}
return _properties;
}
}
public override bool IsEmpty
{
get
{
long? contentLength = GetHttpContentLength();
return contentLength.HasValue && contentLength.Value == 0;
}
}
public override bool IsFault
{
get { return false; }
}
public bool IsRequest { get; private set; }
public HttpRequestMessage GetHttpRequestMessage(bool extract)
{
EnsureNotDisposed();
Contract.Assert(IsRequest, "This method should only be called when IsRequest is true.");
if (extract)
{
HttpRequestMessage req = _request;
_request = null;
return req;
}
return _request;
}
public HttpResponseMessage GetHttpResponseMessage(bool extract)
{
EnsureNotDisposed();
Contract.Assert(!IsRequest, "This method should only be called when IsRequest is false.");
if (extract)
{
HttpResponseMessage res = _response;
_response = null;
return res;
}
return _response;
}
protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
{
throw Error.NotSupported(GetNotSupportedMessage());
}
protected override MessageBuffer OnCreateBufferedCopy(int maxBufferSize)
{
throw Error.NotSupported(GetNotSupportedMessage());
}
protected override XmlDictionaryReader OnGetReaderAtBodyContents()
{
throw Error.NotSupported(GetNotSupportedMessage());
}
protected override string OnGetBodyAttribute(string localName, string ns)
{
throw Error.NotSupported(GetNotSupportedMessage());
}
protected override void OnWriteStartBody(XmlDictionaryWriter writer)
{
throw Error.NotSupported(GetNotSupportedMessage());
}
protected override void OnWriteStartEnvelope(XmlDictionaryWriter writer)
{
throw Error.NotSupported(GetNotSupportedMessage());
}
protected override void OnBodyToString(XmlDictionaryWriter writer)
{
if (writer == null)
{
throw Error.ArgumentNull("writer");
}
long? contentLength = GetHttpContentLength();
string contentString = null;
if (IsRequest)
{
contentString = contentLength.HasValue
? Error.Format(SRResources.MessageBodyIsHttpRequestMessageWithKnownContentLength, contentLength.Value)
: SRResources.MessageBodyIsHttpRequestMessageWithUnknownContentLength;
}
else
{
contentString = contentLength.HasValue
? Error.Format(SRResources.MessageBodyIsHttpResponseMessageWithKnownContentLength, contentLength.Value)
: SRResources.MessageBodyIsHttpResponseMessageWithUnknownContentLength;
}
writer.WriteString(contentString);
}
protected override void OnWriteMessage(XmlDictionaryWriter writer)
{
throw Error.NotSupported(GetNotSupportedMessage());
}
protected override void OnWriteStartHeaders(XmlDictionaryWriter writer)
{
throw Error.NotSupported(GetNotSupportedMessage());
}
protected override void OnClose()
{
base.OnClose();
if (_request != null)
{
_request.DisposeRequestResources();
_request.Dispose();
_request = null;
}
if (_response != null)
{
_response.Dispose();
_response = null;
}
}
private static string GetNotSupportedMessage()
{
return Error.Format(
SRResources.MessageReadWriteCopyNotSupported,
HttpMessageExtensions.ToHttpRequestMessageMethodName,
HttpMessageExtensions.ToHttpResponseMessageMethodName,
typeof(HttpMessage).Name);
}
private void EnsureNotDisposed()
{
if (IsDisposed)
{
throw Error.ObjectDisposed(SRResources.MessageClosed, typeof(Message).Name);
}
}
private long? GetHttpContentLength()
{
HttpContent content = IsRequest
? GetHttpRequestMessage(false).Content
: GetHttpResponseMessage(false).Content;
if (content == null)
{
return 0;
}
return content.Headers.ContentLength;
}
}
}

View File

@ -0,0 +1,270 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.IO;
using System.Net.Http;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http.SelfHost.Properties;
using System.Web.Http.SelfHost.ServiceModel.Channels;
namespace System.Web.Http.SelfHost.Channels
{
internal class HttpMessageEncoderFactory : MessageEncoderFactory
{
private HttpMessageEncoder _encoder;
public HttpMessageEncoderFactory()
{
_encoder = new HttpMessageEncoder();
}
public override MessageEncoder Encoder
{
get { return _encoder; }
}
public override MessageVersion MessageVersion
{
get { return MessageVersion.None; }
}
public override MessageEncoder CreateSessionEncoder()
{
throw Error.NotSupported(SRResources.HttpMessageEncoderFactoryDoesNotSupportSessionEncoder, typeof(HttpMessageEncoderFactory).Name);
}
private class HttpMessageEncoder : MessageEncoder
{
private const string ContentTypeHeaderName = "Content-Type";
private const string MaxSentMessageSizeExceededResourceStringName = "MaxSentMessageSizeExceeded";
private static readonly string _httpBindingClassName = typeof(HttpBinding).FullName;
private static readonly string _httpResponseMessageClassName = typeof(HttpResponseMessage).FullName;
public override string ContentType
{
get { return String.Empty; }
}
public override string MediaType
{
get { return String.Empty; }
}
public override MessageVersion MessageVersion
{
get { return MessageVersion.None; }
}
public override bool IsContentTypeSupported(string contentType)
{
if (contentType == null)
{
throw Error.ArgumentNull("contentType");
}
return true;
}
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "disposed later.")]
public override Message ReadMessage(ArraySegment<byte> buffer, BufferManager bufferManager, string contentType)
{
if (bufferManager == null)
{
throw Error.ArgumentNull("bufferManager");
}
HttpRequestMessage request = new HttpRequestMessage();
request.Content = new ByteArrayBufferManagerContent(bufferManager, buffer.Array, buffer.Offset, buffer.Count);
if (!String.IsNullOrEmpty(contentType))
{
request.Content.Headers.Add(ContentTypeHeaderName, contentType);
}
Message message = request.ToMessage();
message.Properties.Encoder = this;
return message;
}
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "disposed later.")]
public override Message ReadMessage(Stream stream, int maxSizeOfHeaders, string contentType)
{
if (stream == null)
{
throw Error.ArgumentNull("stream");
}
HttpRequestMessage request = new HttpRequestMessage();
request.Content = new StreamContent(stream);
if (!String.IsNullOrEmpty(contentType))
{
request.Content.Headers.Add(ContentTypeHeaderName, contentType);
}
Message message = request.ToMessage();
message.Properties.Encoder = this;
return message;
}
public override ArraySegment<byte> WriteMessage(Message message, int maxMessageSize, BufferManager bufferManager, int messageOffset)
{
if (message == null)
{
throw Error.ArgumentNull("message");
}
if (bufferManager == null)
{
throw Error.ArgumentNull("bufferManager");
}
if (maxMessageSize < 0)
{
throw Error.ArgumentOutOfRange("maxMessageSize", maxMessageSize, SRResources.NonnegativeNumberRequired);
}
if (messageOffset < 0)
{
throw Error.ArgumentOutOfRange("messageOffset", messageOffset, SRResources.NonnegativeNumberRequired);
}
if (messageOffset > maxMessageSize)
{
throw Error.Argument(String.Empty, SRResources.ParameterMustBeLessThanOrEqualSecondParameter, "messageOffset", "maxMessageSize");
}
// TODO: DevDiv2 bug #378887 -- find out how to eliminate this middle buffer
using (BufferManagerOutputStream stream = new BufferManagerOutputStream(MaxSentMessageSizeExceededResourceStringName, 0, maxMessageSize, bufferManager))
{
int num;
stream.Skip(messageOffset);
WriteMessage(message, stream);
byte[] buffer = stream.ToArray(out num);
ArraySegment<byte> messageData = new ArraySegment<byte>(buffer, 0, num - messageOffset);
// ToArray transfers full ownership of buffer to us, meaning we are responsible for returning it to BufferManager.
// But we must delay that release until WCF has finished with the buffer we are returning from this method.
HttpMessageEncodingRequestContext requestContext = HttpMessageEncodingRequestContext.GetContextFromMessage(message);
Contract.Assert(requestContext != null);
requestContext.BufferManager = bufferManager;
requestContext.BufferToReturn = buffer;
return messageData;
}
}
[SuppressMessage("Microsoft.WebAPI", "CR4001:DoNotCallProblematicMethodsOnTask", Justification = "The WriteMessage() API is synchronous, and Wait() won't deadlock in self-host.")]
public override void WriteMessage(Message message, Stream stream)
{
if (message == null)
{
throw Error.ArgumentNull("message");
}
if (stream == null)
{
throw Error.ArgumentNull("stream");
}
ThrowIfMismatchedMessageVersion(message);
message.Properties.Encoder = this;
HttpResponseMessage response = GetHttpResponseMessageOrThrow(message);
if (response.Content != null)
{
HttpMessageEncodingRequestContext requestContext =
HttpMessageEncodingRequestContext.GetContextFromMessage(message);
try
{
response.Content.CopyToAsync(stream)
.Catch((info) =>
{
if (requestContext != null)
{
requestContext.Exception = info.Exception;
}
return info.Throw();
})
.Wait();
}
catch (Exception ex)
{
if (requestContext != null)
{
requestContext.Exception = ex;
}
throw;
}
}
}
internal void ThrowIfMismatchedMessageVersion(Message message)
{
if (message.Version != MessageVersion)
{
throw new ProtocolException(Error.Format(SRResources.EncoderMessageVersionMismatch, message.Version, MessageVersion));
}
}
private static HttpResponseMessage GetHttpResponseMessageOrThrow(Message message)
{
HttpResponseMessage response = message.ToHttpResponseMessage();
if (response == null)
{
throw Error.InvalidOperation(
SRResources.MessageInvalidForHttpMessageEncoder,
_httpBindingClassName,
HttpMessageExtensions.ToMessageMethodName,
_httpResponseMessageClassName);
}
return response;
}
private class ByteArrayBufferManagerContent : ByteArrayContent
{
private BufferManager _bufferManager;
private byte[] _content;
public ByteArrayBufferManagerContent(BufferManager bufferManager, byte[] content, int offset, int count)
: base(content, offset, count)
{
Contract.Assert(bufferManager != null, "The 'bufferManager' parameter should never be null.");
_bufferManager = bufferManager;
_content = content;
}
protected override void Dispose(bool disposing)
{
try
{
if (disposing)
{
BufferManager oldBufferManager = Interlocked.Exchange(ref _bufferManager, null);
if (oldBufferManager != null)
{
oldBufferManager.ReturnBuffer(_content);
_content = null;
}
}
}
finally
{
base.Dispose(disposing);
}
}
}
}
}
}

View File

@ -0,0 +1,140 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Diagnostics.CodeAnalysis;
using System.ServiceModel.Channels;
using System.Web.Http.SelfHost.Properties;
namespace System.Web.Http.SelfHost.Channels
{
/// <summary>
/// Provides an <see cref="HttpMessageEncoderFactory"/> that returns a <see cref="MessageEncoder"/>
/// that is able to produce and consume <see cref="HttpMessage"/> instances.
/// </summary>
internal sealed class HttpMessageEncodingBindingElement : MessageEncodingBindingElement
{
private static readonly Type _replyChannelType = typeof(IReplyChannel);
/// <summary>
/// Gets or sets the message version that can be handled by the message encoders produced by the message encoder factory.
/// </summary>
/// <returns>The <see cref="MessageVersion"/> used by the encoders produced by the message encoder factory.</returns>
public override MessageVersion MessageVersion
{
get { return MessageVersion.None; }
set
{
if (value == null)
{
throw Error.ArgumentNull("value");
}
if (value != MessageVersion.None)
{
throw Error.NotSupported(SRResources.OnlyMessageVersionNoneSupportedOnHttpMessageEncodingBindingElement, typeof(HttpMessageEncodingBindingElement).Name);
}
}
}
/// <summary>
/// Returns a value that indicates whether the binding element can build a listener for a specific type of channel.
/// </summary>
/// <typeparam name="TChannel">The type of channel the listener accepts.</typeparam>
/// <param name="context">The <see cref="BindingContext"/> that provides context for the binding element</param>
/// <returns>true if the <see cref="IChannelListener{TChannel}"/> of type <see cref="IChannel"/> can be built by the binding element; otherwise, false.</returns>
[SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "Existing public API")]
public override bool CanBuildChannelFactory<TChannel>(BindingContext context)
{
return false;
}
/// <summary>
/// Returns a value that indicates whether the binding element can build a channel factory for a specific type of channel.
/// </summary>
/// <typeparam name="TChannel">The type of channel the channel factory produces.</typeparam>
/// <param name="context">The <see cref="BindingContext"/> that provides context for the binding element</param>
/// <returns>ALways false.</returns>
[SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "Existing public API")]
public override IChannelFactory<TChannel> BuildChannelFactory<TChannel>(BindingContext context)
{
throw Error.NotSupported(SRResources.ChannelFactoryNotSupported, typeof(HttpMessageEncodingBindingElement).Name, typeof(IChannelFactory).Name);
}
/// <summary>
/// Returns a value that indicates whether the binding element can build a channel factory for a specific type of channel.
/// </summary>
/// <typeparam name="TChannel">The type of channel the channel factory produces.</typeparam>
/// <param name="context">The <see cref="BindingContext"/> that provides context for the binding element</param>
/// <returns>ALways false.</returns>
[SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "Existing public API")]
public override bool CanBuildChannelListener<TChannel>(BindingContext context)
{
if (context == null)
{
throw Error.ArgumentNull("context");
}
context.BindingParameters.Add(this);
return IsChannelShapeSupported<TChannel>() && context.CanBuildInnerChannelListener<TChannel>();
}
/// <summary>
/// Initializes a channel listener to accept channels of a specified type from the binding context.
/// </summary>
/// <typeparam name="TChannel">The type of channel the listener is built to accept.</typeparam>
/// <param name="context">The <see cref="BindingContext"/> that provides context for the binding element</param>
/// <returns>The <see cref="IChannelListener{TChannel}"/> of type <see cref="IChannel"/> initialized from the context.</returns>
[SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "Existing public API")]
public override IChannelListener<TChannel> BuildChannelListener<TChannel>(BindingContext context)
{
if (context == null)
{
throw Error.ArgumentNull("context");
}
if (!IsChannelShapeSupported<TChannel>())
{
throw Error.NotSupported(SRResources.ChannelShapeNotSupported, typeof(HttpMessageEncodingBindingElement).Name, typeof(IReplyChannel).Name);
}
context.BindingParameters.Add(this);
IChannelListener<IReplyChannel> innerListener = context.BuildInnerChannelListener<IReplyChannel>();
if (innerListener == null)
{
return null;
}
return (IChannelListener<TChannel>)new HttpMessageEncodingChannelListener(context.Binding, innerListener);
}
/// <summary>
/// Returns a copy of the binding element object.
/// </summary>
/// <returns>A <see cref="BindingElement"/> object that is a deep clone of the original.</returns>
public override BindingElement Clone()
{
return new HttpMessageEncodingBindingElement();
}
/// <summary>
/// Creates a factory for producing message encoders that are able to
/// produce and consume <see cref="HttpMessage"/> instances.
/// </summary>
/// <returns>
/// The <see cref="MessageEncoderFactory"/> used to produce message encoders that are able to
/// produce and consume <see cref="HttpMessage"/> instances.
/// </returns>
public override MessageEncoderFactory CreateMessageEncoderFactory()
{
return new HttpMessageEncoderFactory();
}
private static bool IsChannelShapeSupported<TChannel>()
{
return typeof(TChannel) == _replyChannelType;
}
}
}

View File

@ -0,0 +1,62 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.ServiceModel.Channels;
using System.Web.Http.SelfHost.ServiceModel.Channels;
namespace System.Web.Http.SelfHost.Channels
{
internal class HttpMessageEncodingChannelListener : LayeredChannelListener<IReplyChannel>
{
private IChannelListener<IReplyChannel> _innerChannelListener;
public HttpMessageEncodingChannelListener(Binding binding, IChannelListener<IReplyChannel> innerListener) :
base(binding, innerListener)
{
}
protected override void OnOpening()
{
_innerChannelListener = (IChannelListener<IReplyChannel>)InnerChannelListener;
base.OnOpening();
}
protected override IReplyChannel OnAcceptChannel(TimeSpan timeout)
{
IReplyChannel innerChannel = _innerChannelListener.AcceptChannel(timeout);
return WrapInnerChannel(innerChannel);
}
protected override IAsyncResult OnBeginAcceptChannel(TimeSpan timeout, AsyncCallback callback, object state)
{
return _innerChannelListener.BeginAcceptChannel(timeout, callback, state);
}
protected override IReplyChannel OnEndAcceptChannel(IAsyncResult result)
{
IReplyChannel innerChannel = _innerChannelListener.EndAcceptChannel(result);
return WrapInnerChannel(innerChannel);
}
protected override IAsyncResult OnBeginWaitForChannel(TimeSpan timeout, AsyncCallback callback, object state)
{
return _innerChannelListener.BeginWaitForChannel(timeout, callback, state);
}
protected override bool OnEndWaitForChannel(IAsyncResult result)
{
return _innerChannelListener.EndWaitForChannel(result);
}
protected override bool OnWaitForChannel(TimeSpan timeout)
{
return _innerChannelListener.WaitForChannel(timeout);
}
private IReplyChannel WrapInnerChannel(IReplyChannel innerChannel)
{
return (innerChannel != null)
? new HttpMessageEncodingReplyChannel(this, innerChannel)
: (IReplyChannel)null;
}
}
}

View File

@ -0,0 +1,104 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Diagnostics.CodeAnalysis;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Web.Http.SelfHost.ServiceModel.Channels;
namespace System.Web.Http.SelfHost.Channels
{
internal class HttpMessageEncodingReplyChannel : LayeredChannel<IReplyChannel>, IReplyChannel, IChannel, ICommunicationObject
{
public HttpMessageEncodingReplyChannel(ChannelManagerBase channelManager, IReplyChannel innerChannel)
: base(channelManager, innerChannel)
{
}
public EndpointAddress LocalAddress
{
get { return InnerChannel.LocalAddress; }
}
public IAsyncResult BeginReceiveRequest(AsyncCallback callback, object state)
{
return InnerChannel.BeginReceiveRequest(callback, state);
}
public IAsyncResult BeginReceiveRequest(TimeSpan timeout, AsyncCallback callback, object state)
{
return InnerChannel.BeginReceiveRequest(timeout, callback, state);
}
public IAsyncResult BeginTryReceiveRequest(TimeSpan timeout, AsyncCallback callback, object state)
{
return InnerChannel.BeginTryReceiveRequest(timeout, callback, state);
}
public IAsyncResult BeginWaitForRequest(TimeSpan timeout, AsyncCallback callback, object state)
{
return InnerChannel.BeginWaitForRequest(timeout, callback, state);
}
public RequestContext EndReceiveRequest(IAsyncResult result)
{
RequestContext innerContext = InnerChannel.EndReceiveRequest(result);
return WrapRequestContext(innerContext);
}
public bool EndTryReceiveRequest(IAsyncResult result, out RequestContext context)
{
RequestContext innerContext;
context = null;
if (!InnerChannel.EndTryReceiveRequest(result, out innerContext))
{
return false;
}
context = WrapRequestContext(innerContext);
return true;
}
public bool EndWaitForRequest(IAsyncResult result)
{
return InnerChannel.EndWaitForRequest(result);
}
public RequestContext ReceiveRequest()
{
RequestContext innerContext = InnerChannel.ReceiveRequest();
return WrapRequestContext(innerContext);
}
public RequestContext ReceiveRequest(TimeSpan timeout)
{
RequestContext innerContext = InnerChannel.ReceiveRequest(timeout);
return WrapRequestContext(innerContext);
}
public bool TryReceiveRequest(TimeSpan timeout, out RequestContext context)
{
RequestContext innerContext;
if (InnerChannel.TryReceiveRequest(timeout, out innerContext))
{
context = WrapRequestContext(innerContext);
return true;
}
context = null;
return false;
}
public bool WaitForRequest(TimeSpan timeout)
{
return InnerChannel.WaitForRequest(timeout);
}
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "disposed later.")]
private static RequestContext WrapRequestContext(RequestContext innerContext)
{
return (innerContext != null)
? new HttpMessageEncodingRequestContext(innerContext)
: (RequestContext)null;
}
}
}

View File

@ -0,0 +1,275 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.ServiceModel.Channels;
using System.Web.Http.SelfHost.Properties;
namespace System.Web.Http.SelfHost.Channels
{
internal class HttpMessageEncodingRequestContext : RequestContext
{
private const string HttpMessageEncodingRequestContextPropertyName = "MS_HttpMessageEncodingRequestContextKey";
private const string DefaultReasonPhrase = "OK";
private RequestContext _innerContext;
private Message _configuredRequestMessage;
public HttpMessageEncodingRequestContext(RequestContext innerContext)
{
Contract.Assert(innerContext != null, "The 'innerContext' parameter should not be null.");
_innerContext = innerContext;
}
internal Exception Exception { get; set; }
internal BufferManager BufferManager { get; set; }
internal byte[] BufferToReturn { get; set; }
public override Message RequestMessage
{
get
{
if (_configuredRequestMessage == null)
{
_configuredRequestMessage = ConfigureRequestMessage(_innerContext.RequestMessage);
}
return _configuredRequestMessage;
}
}
public override void Abort()
{
Cleanup();
_innerContext.Abort();
}
public override IAsyncResult BeginReply(Message message, TimeSpan timeout, AsyncCallback callback, object state)
{
ConfigureResponseMessage(message);
return _innerContext.BeginReply(message, timeout, callback, state);
}
public override IAsyncResult BeginReply(Message message, AsyncCallback callback, object state)
{
ConfigureResponseMessage(message);
return _innerContext.BeginReply(message, callback, state);
}
public override void Close(TimeSpan timeout)
{
Cleanup();
_innerContext.Close(timeout);
}
public override void Close()
{
Cleanup();
_innerContext.Close();
}
public override void EndReply(IAsyncResult result)
{
try
{
_innerContext.EndReply(result);
}
catch (Exception ex)
{
Exception = ex;
throw;
}
}
public override void Reply(Message message, TimeSpan timeout)
{
ConfigureResponseMessage(message);
_innerContext.Reply(message, timeout);
}
public override void Reply(Message message)
{
ConfigureResponseMessage(message);
_innerContext.Reply(message);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
// To avoid double buffering, we use the BufferedOutputStream's own buffer
// that it created through the BufferManager passed to WriteStream.
// We are responsible for returning that buffer to the BufferManager
// because we used BufferedOutputStream.ToArray to take ownership
// of its buffers.
if (BufferManager != null && BufferToReturn != null)
{
BufferManager.ReturnBuffer(BufferToReturn);
BufferToReturn = null;
}
}
base.Dispose(disposing);
}
internal static HttpMessageEncodingRequestContext GetContextFromMessage(Message message)
{
HttpMessageEncodingRequestContext context = null;
message.Properties.TryGetValue<HttpMessageEncodingRequestContext>(HttpMessageEncodingRequestContextPropertyName, out context);
return context;
}
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Cleanup exceptions are ignored as they are not fatal to the host.")]
private void Cleanup()
{
if (_configuredRequestMessage != null)
{
try
{
_configuredRequestMessage.Close();
}
catch
{
}
}
}
private static void CopyHeadersToNameValueCollection(HttpHeaders headers, NameValueCollection nameValueCollection)
{
foreach (KeyValuePair<string, IEnumerable<string>> header in headers)
{
foreach (string value in header.Value)
{
nameValueCollection.Add(header.Key, value);
}
}
}
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "disposed later.")]
private static Message ConfigureRequestMessage(Message message)
{
if (message == null)
{
return null;
}
HttpRequestMessageProperty requestProperty;
if (!message.Properties.TryGetValue(HttpRequestMessageProperty.Name, out requestProperty))
{
throw Error.InvalidOperation(
SRResources.RequestMissingHttpRequestMessageProperty,
HttpRequestMessageProperty.Name,
typeof(HttpRequestMessageProperty).Name);
}
Uri uri = message.Headers.To;
if (uri == null)
{
throw Error.InvalidOperation(SRResources.RequestMissingToHeader);
}
HttpRequestMessage httpRequestMessage = message.ToHttpRequestMessage();
if (httpRequestMessage == null)
{
if (!message.IsEmpty)
{
throw Error.InvalidOperation(SRResources.NonHttpMessageMustBeEmpty, HttpMessageExtensions.ToHttpRequestMessageMethodName, typeof(HttpMessage).Name);
}
httpRequestMessage = new HttpRequestMessage();
Message oldMessage = message;
message = httpRequestMessage.ToMessage();
message.Properties.CopyProperties(oldMessage.Properties);
oldMessage.Close();
}
else
{
// Clear headers but not properties.
message.Headers.Clear();
}
// Copy message properties to HttpRequestMessage. While it does have the
// risk of allowing properties to get out of sync they in virtually all cases are
// read-only so the risk is low. The downside to not doing it is that it isn't
// possible to access anything from HttpRequestMessage (or OperationContent.Current)
// which is worse.
foreach (KeyValuePair<string, object> kv in message.Properties)
{
httpRequestMessage.Properties.Add(kv.Key, kv.Value);
}
if (httpRequestMessage.Content == null)
{
httpRequestMessage.Content = new ByteArrayContent(new byte[0]);
}
else
{
httpRequestMessage.Content.Headers.Clear();
}
message.Headers.To = uri;
httpRequestMessage.RequestUri = uri;
httpRequestMessage.Method = HttpMethodHelper.GetHttpMethod(requestProperty.Method);
foreach (var headerName in requestProperty.Headers.AllKeys)
{
string headerValue = requestProperty.Headers[headerName];
if (!httpRequestMessage.Headers.TryAddWithoutValidation(headerName, headerValue))
{
httpRequestMessage.Content.Headers.TryAddWithoutValidation(headerName, headerValue);
}
}
return message;
}
private void ConfigureResponseMessage(Message message)
{
Contract.Assert(message != null);
HttpResponseMessageProperty responseProperty = new HttpResponseMessageProperty();
HttpResponseMessage httpResponseMessage = message.ToHttpResponseMessage();
if (httpResponseMessage == null)
{
responseProperty.StatusCode = HttpStatusCode.InternalServerError;
responseProperty.SuppressEntityBody = true;
}
else
{
responseProperty.StatusCode = httpResponseMessage.StatusCode;
if (httpResponseMessage.ReasonPhrase != null &&
httpResponseMessage.ReasonPhrase != DefaultReasonPhrase)
{
responseProperty.StatusDescription = httpResponseMessage.ReasonPhrase;
}
CopyHeadersToNameValueCollection(httpResponseMessage.Headers, responseProperty.Headers);
HttpContent content = httpResponseMessage.Content;
if (content != null)
{
CopyHeadersToNameValueCollection(httpResponseMessage.Content.Headers, responseProperty.Headers);
}
else
{
responseProperty.SuppressEntityBody = true;
}
}
message.Properties.Clear();
message.Headers.Clear();
message.Properties.Add(HttpResponseMessageProperty.Name, responseProperty);
// The current request context flows with the Message for later use
// by HttpMessageEncoder.WriteMessage
message.Properties.Add(HttpMessageEncodingRequestContextPropertyName, this);
}
}
}

View File

@ -0,0 +1,189 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Net.Http;
using System.ServiceModel.Channels;
namespace System.Web.Http.SelfHost.Channels
{
/// <summary>
/// Provides extension methods for getting an <see cref="HttpRequestMessage"/> instance or
/// an <see cref="HttpResponseMessage"/> instance from a <see cref="Message"/> instance and
/// provides extension methods for creating a <see cref="Message"/> instance from either an
/// <see cref="HttpRequestMessage"/> instance or an
/// <see cref="HttpResponseMessage"/> instance.
/// </summary>
internal static class HttpMessageExtensions
{
internal const string ToHttpRequestMessageMethodName = "ToHttpRequestMessage";
internal const string ToHttpResponseMessageMethodName = "ToHttpResponseMessage";
internal const string ToMessageMethodName = "ToMessage";
/// <summary>
/// Returns a reference to the <see cref="HttpRequestMessage"/>
/// instance held by the given <see cref="Message"/> or null if the <see cref="Message"/> does not
/// hold a reference to an <see cref="HttpRequestMessage"/>
/// instance.
/// </summary>
/// <param name="message">The given <see cref="Message"/> that holds a reference to an
/// <see cref="HttpRequestMessage"/> instance.
/// </param>
/// <returns>
/// A reference to the <see cref="HttpRequestMessage"/>
/// instance held by the given <see cref="Message"/> or null if the <see cref="Message"/> does not
/// hold a reference to an <see cref="HttpRequestMessage"/>
/// instance.
/// </returns>
public static HttpRequestMessage ToHttpRequestMessage(this Message message)
{
if (message == null)
{
throw Error.ArgumentNull("message");
}
HttpMessage httpMessage = message as HttpMessage;
if (httpMessage != null && httpMessage.IsRequest)
{
return httpMessage.GetHttpRequestMessage(false);
}
return null;
}
/// <summary>
/// Returns a reference to the <see cref="HttpRequestMessage"/>
/// instance held by the given <see cref="Message"/> or null if the <see cref="Message"/> does not
/// hold a reference to an <see cref="HttpRequestMessage"/>
/// instance.
/// </summary>
/// <remarks>The caller takes over the ownership of the associated <see cref="HttpRequestMessage"/> and is responsible for its disposal.</remarks>
/// <param name="message">The given <see cref="Message"/> that holds a reference to an
/// <see cref="HttpRequestMessage"/> instance.
/// </param>
/// <returns>
/// A reference to the <see cref="HttpRequestMessage"/>
/// instance held by the given <see cref="Message"/> or null if the <see cref="Message"/> does not
/// hold a reference to an <see cref="HttpRequestMessage"/>
/// instance.
/// The caller is responsible for disposing any <see cref="HttpRequestMessage"/> instance returned.
/// </returns>
public static HttpRequestMessage ExtractHttpRequestMessage(this Message message)
{
if (message == null)
{
throw Error.ArgumentNull("message");
}
HttpMessage httpMessage = message as HttpMessage;
if (httpMessage != null && httpMessage.IsRequest)
{
return httpMessage.GetHttpRequestMessage(true);
}
return null;
}
/// <summary>
/// Returns a reference to the <see cref="HttpResponseMessage"/>
/// instance held by the given <see cref="Message"/> or null if the <see cref="Message"/> does not
/// hold a reference to an <see cref="HttpResponseMessage"/>
/// instance.
/// </summary>
/// <param name="message">The given <see cref="Message"/> that holds a reference to an
/// <see cref="HttpResponseMessage"/> instance.
/// </param>
/// <returns>
/// A reference to the <see cref="HttpResponseMessage"/>
/// instance held by the given <see cref="Message"/> or null if the <see cref="Message"/> does not
/// hold a reference to an <see cref="HttpResponseMessage"/>
/// instance.
/// </returns>
public static HttpResponseMessage ToHttpResponseMessage(this Message message)
{
if (message == null)
{
throw Error.ArgumentNull("message");
}
HttpMessage httpMessage = message as HttpMessage;
if (httpMessage != null && !httpMessage.IsRequest)
{
return httpMessage.GetHttpResponseMessage(false);
}
return null;
}
/// <summary>
/// Returns a reference to the <see cref="HttpResponseMessage"/>
/// instance held by the given <see cref="Message"/> or null if the <see cref="Message"/> does not
/// hold a reference to an <see cref="HttpResponseMessage"/>
/// instance.
/// </summary>
/// <remarks>The caller takes over the ownership of the associated <see cref="HttpRequestMessage"/> and is responsible for its disposal.</remarks>
/// <param name="message">The given <see cref="Message"/> that holds a reference to an
/// <see cref="HttpResponseMessage"/> instance.
/// </param>
/// <returns>
/// A reference to the <see cref="HttpResponseMessage"/>
/// instance held by the given <see cref="Message"/> or null if the <see cref="Message"/> does not
/// hold a reference to an <see cref="HttpResponseMessage"/>
/// instance.
/// The caller is responsible for disposing any <see cref="HttpResponseMessage"/> instance returned.
/// </returns>
public static HttpResponseMessage ExtractHttpResponseMessage(this Message message)
{
if (message == null)
{
throw Error.ArgumentNull("message");
}
HttpMessage httpMessage = message as HttpMessage;
if (httpMessage != null && !httpMessage.IsRequest)
{
return httpMessage.GetHttpResponseMessage(true);
}
return null;
}
/// <summary>
/// Creates a new <see cref="Message"/> that holds a reference to the given
/// <see cref="HttpRequestMessage"/> instance.
/// </summary>
/// <param name="request">The <see cref="HttpRequestMessage"/>
/// instance to which the new <see cref="Message"/> should hold a reference.
/// </param>
/// <returns>A <see cref="Message"/> that holds a reference to the given
/// <see cref="HttpRequestMessage"/> instance.
/// </returns>
public static Message ToMessage(this HttpRequestMessage request)
{
if (request == null)
{
throw Error.ArgumentNull("request");
}
return new HttpMessage(request);
}
/// <summary>
/// Creates a new <see cref="Message"/> that holds a reference to the given
/// <see cref="HttpResponseMessage"/> instance.
/// </summary>
/// <param name="response">The <see cref="HttpResponseMessage"/>
/// instance to which the new <see cref="Message"/> should hold a reference.
/// </param>
/// <returns>A <see cref="Message"/> that holds a reference to the given
/// <see cref="HttpResponseMessage"/> instance.
/// </returns>
public static Message ToMessage(this HttpResponseMessage response)
{
if (response == null)
{
throw Error.ArgumentNull("response");
}
return new HttpMessage(response);
}
}
}

View File

@ -0,0 +1,11 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Diagnostics.CodeAnalysis;
[assembly: SuppressMessage("Microsoft.Design", "CA2210:AssembliesShouldHaveValidStrongNames", Justification = "These assemblies are delay-signed.")]
[assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Justification = "Classes are grouped logically for user clarity.", Scope = "Namespace", Target = "System.Net.Http")]
[assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Justification = "Classes are grouped logically for user clarity.", Scope = "Namespace", Target = "System.Web.Http.SelfHost")]
[assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Justification = "Classes are grouped logically for user clarity.", Scope = "Namespace", Target = "System.Web.Http.SelfHost.Activation")]
[assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Justification = "Classes are grouped logically for user clarity.", Scope = "Namespace", Target = "System.Web.Http.SelfHost.Channels")]
[assembly: SuppressMessage("Microsoft.Naming", "CA1701:ResourceStringCompoundWordsShouldBeCasedCorrectly", MessageId = "URIs", Scope = "resource", Target = "System.Web.Http.SelfHost.Properties.SRResources.resources", Justification = "FxCop does not seem to allow adding an exception to this term in its dictionary.")]
[assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "URIs", Scope = "resource", Target = "System.Web.Http.SelfHost.Properties.SRResources.resources", Justification = "FxCop does not seem to allow adding an exception to this term in its dictionary.")]

View File

@ -0,0 +1,37 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.ComponentModel;
using System.ServiceModel.Security;
using System.Web.Http;
namespace System.Net.Http
{
[EditorBrowsable(EditorBrowsableState.Never)]
public static class HttpRequestMessageExtensions
{
private const string SecurityKey = "Security";
/// <summary>
/// Gets the current <see cref="T:System.ServiceModel.Security.SecurityMessageProperty"/>
/// stored in <see cref="M:HttpRequestMessage.Properties"/> for the given request.
/// </summary>
/// <param name="request">The HTTP request.</param>
/// <returns>The <see cref="SecurityMessageProperty"/>.</returns>
public static SecurityMessageProperty GetSecurityMessageProperty(this HttpRequestMessage request)
{
if (request == null)
{
throw Error.ArgumentNull("request");
}
return request.GetProperty<SecurityMessageProperty>(SecurityKey);
}
private static T GetProperty<T>(this HttpRequestMessage request, string key)
{
T value;
request.Properties.TryGetValue(key, out value);
return value;
}
}
}

View File

@ -0,0 +1,343 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Diagnostics.CodeAnalysis;
using System.IdentityModel.Selectors;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Security;
using System.Web.Http.SelfHost.Channels;
using System.Web.Http.SelfHost.Properties;
using System.Web.Http.SelfHost.ServiceModel;
using System.Web.Http.SelfHost.ServiceModel.Channels;
namespace System.Web.Http.SelfHost
{
/// <summary>
/// The configuration class for Http Services
/// </summary>
public class HttpSelfHostConfiguration : HttpConfiguration
{
private const int DefaultMaxConcurrentRequests = 100;
private const int DefaultMaxBufferSize = 64 * 1024;
private const int DefaultReceivedMessageSize = 64 * 1024;
private const int PendingContextFactor = 100;
private const int MinConcurrentRequests = 1;
private const int MinBufferSize = 1;
private const int MinReceivedMessageSize = 1;
private Uri _baseAddress;
private int _maxConcurrentRequests;
private ServiceCredentials _credentials = new ServiceCredentials();
private bool _useWindowsAuth;
private TransferMode _transferMode;
private int _maxBufferSize = DefaultMaxBufferSize;
private bool _maxBufferSizeIsInitialized;
private long _maxReceivedMessageSize = DefaultReceivedMessageSize;
private HostNameComparisonMode _hostNameComparisonMode;
/// <summary>
/// Initializes a new instance of the <see cref="HttpSelfHostConfiguration"/> class.
/// </summary>
/// <param name="baseAddress">The base address.</param>
public HttpSelfHostConfiguration(string baseAddress)
: this(CreateBaseAddress(baseAddress))
{
}
/// <summary>
/// Initializes a new instance of the <see cref="HttpSelfHostConfiguration"/> class.
/// </summary>
/// <param name="baseAddress">The base address.</param>
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "caller owns object")]
public HttpSelfHostConfiguration(Uri baseAddress)
: base(new HttpRouteCollection(ValidateBaseAddress(baseAddress).AbsolutePath))
{
_baseAddress = ValidateBaseAddress(baseAddress);
_maxConcurrentRequests = GetDefaultMaxConcurrentRequests();
_maxBufferSize = TransportDefaults.MaxBufferSize;
_maxReceivedMessageSize = TransportDefaults.MaxReceivedMessageSize;
}
/// <summary>
/// Gets the base address.
/// </summary>
/// <value>
/// The base address.
/// </value>
public Uri BaseAddress
{
get { return _baseAddress; }
}
/// <summary>
/// Gets or sets the upper limit of how many concurrent <see cref="T:System.Net.Http.HttpRequestMessage"/> instances
/// can be processed at any given time. The default is 100 times the number of CPU cores.
/// </summary>
/// <value>
/// The maximum concurrent <see cref="T:System.Net.Http.HttpRequestMessage"/> instances processed at any given time.
/// </value>
public int MaxConcurrentRequests
{
get { return _maxConcurrentRequests; }
set
{
if (value < MinConcurrentRequests)
{
throw Error.ArgumentGreaterThanOrEqualTo("value", value, MinConcurrentRequests);
}
_maxConcurrentRequests = value;
}
}
/// <summary>
/// Gets or sets the transfer mode.
/// </summary>
/// <value>
/// The transfer mode.
/// </value>
public TransferMode TransferMode
{
get { return _transferMode; }
set
{
TransferModeHelper.Validate(value);
_transferMode = value;
}
}
/// <summary>
/// Specifies how the host name should be used in URI comparisons when dispatching an incoming message.
/// </summary>
public HostNameComparisonMode HostNameComparisonMode
{
get { return _hostNameComparisonMode; }
set
{
HostNameComparisonModeHelper.Validate(value);
_hostNameComparisonMode = value;
}
}
/// <summary>
/// Gets or sets the size of the max buffer.
/// </summary>
/// <value>
/// The size of the max buffer.
/// </value>
public int MaxBufferSize
{
get
{
if (_maxBufferSizeIsInitialized || TransferMode != TransferMode.Buffered)
{
return _maxBufferSize;
}
long maxReceivedMessageSize = MaxReceivedMessageSize;
if (maxReceivedMessageSize > Int32.MaxValue)
{
return Int32.MaxValue;
}
return (int)maxReceivedMessageSize;
}
set
{
if (value < MinBufferSize)
{
throw Error.ArgumentGreaterThanOrEqualTo("value", value, MinBufferSize);
}
_maxBufferSizeIsInitialized = true;
_maxBufferSize = value;
}
}
/// <summary>
/// Gets or sets the size of the max received message.
/// </summary>
/// <value>
/// The size of the max received message.
/// </value>
public long MaxReceivedMessageSize
{
get { return _maxReceivedMessageSize; }
set
{
if (value < MinReceivedMessageSize)
{
throw Error.ArgumentGreaterThanOrEqualTo("value", value, MinReceivedMessageSize);
}
_maxReceivedMessageSize = value;
}
}
/// <summary>
/// Gets or sets UserNamePasswordValidator so that it can be used to validate the username and password
/// sent over HTTP or HTTPS
/// </summary>
/// <value>
/// The server certificate.
/// </value>
public UserNamePasswordValidator UserNamePasswordValidator
{
get { return _credentials.UserNameAuthentication.CustomUserNamePasswordValidator; }
set { _credentials.UserNameAuthentication.CustomUserNamePasswordValidator = value; }
}
/// <summary>
/// Use this flag to indicate that you want to use windows authentication. This flag can
/// not be used together with UserNamePasswordValidator property since you can either use
/// Windows or Username Password as client credential.
/// </summary>
/// <value>
/// set it true if you want to use windows authentication
/// </value>
public bool UseWindowsAuthentication
{
get { return _useWindowsAuth; }
set { _useWindowsAuth = value; }
}
/// <summary>
/// Internal method called to configure <see cref="HttpBinding"/> settings.
/// </summary>
/// <param name="httpBinding">Http binding.</param>
/// <returns>The <see cref="BindingParameterCollection"/> to use when building the <see cref="IChannelListener"/> or null if no binding parameters are present.</returns>
internal BindingParameterCollection ConfigureBinding(HttpBinding httpBinding)
{
return OnConfigureBinding(httpBinding);
}
/// <summary>
/// Called to apply the configuration on the endpoint level.
/// </summary>
/// <param name="httpBinding">Http endpoint.</param>
/// <returns>The <see cref="BindingParameterCollection"/> to use when building the <see cref="IChannelListener"/> or null if no binding parameters are present.</returns>
protected virtual BindingParameterCollection OnConfigureBinding(HttpBinding httpBinding)
{
if (httpBinding == null)
{
throw Error.ArgumentNull("httpBinding");
}
if (_useWindowsAuth && _credentials.UserNameAuthentication.CustomUserNamePasswordValidator != null)
{
throw Error.InvalidOperation(SRResources.CannotUseWindowsAuthWithUserNamePasswordValidator);
}
httpBinding.MaxBufferSize = MaxBufferSize;
httpBinding.MaxReceivedMessageSize = MaxReceivedMessageSize;
httpBinding.TransferMode = TransferMode;
httpBinding.HostNameComparisonMode = HostNameComparisonMode;
if (_baseAddress.Scheme == Uri.UriSchemeHttps)
{
// we need to use SSL
httpBinding.Security = new HttpBindingSecurity()
{
Mode = HttpBindingSecurityMode.Transport,
};
}
// Set up binding parameters
if (_credentials.UserNameAuthentication.CustomUserNamePasswordValidator != null)
{
_credentials.UserNameAuthentication.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom;
if (httpBinding.Security == null || httpBinding.Security.Mode == HttpBindingSecurityMode.None)
{
// Basic over HTTP case
httpBinding.Security = new HttpBindingSecurity()
{
Mode = HttpBindingSecurityMode.TransportCredentialOnly,
};
}
// We have validator, so we can set the client credential type to be basic
httpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
return AddCredentialsToBindingParameters();
}
else if (_useWindowsAuth)
{
if (httpBinding.Security == null || httpBinding.Security.Mode == HttpBindingSecurityMode.None)
{
// Basic over HTTP case, should we even allow this?
httpBinding.Security = new HttpBindingSecurity()
{
Mode = HttpBindingSecurityMode.TransportCredentialOnly,
};
}
// We have validator, so we can set the client credential type to be windows
httpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
return AddCredentialsToBindingParameters();
}
return null;
}
private BindingParameterCollection AddCredentialsToBindingParameters()
{
BindingParameterCollection bindingParameters = new BindingParameterCollection();
bindingParameters.Add(_credentials);
return bindingParameters;
}
private static Uri CreateBaseAddress(string baseAddress)
{
if (baseAddress == null)
{
throw Error.ArgumentNull("baseAddress");
}
return new Uri(baseAddress, UriKind.RelativeOrAbsolute);
}
private static Uri ValidateBaseAddress(Uri baseAddress)
{
if (baseAddress == null)
{
throw Error.ArgumentNull("baseAddress");
}
if (!baseAddress.IsAbsoluteUri)
{
throw Error.ArgumentUriNotAbsolute("baseAddress", baseAddress);
}
if (!String.IsNullOrEmpty(baseAddress.Query) || !String.IsNullOrEmpty(baseAddress.Fragment))
{
throw Error.ArgumentUriHasQueryOrFragment("baseAddress", baseAddress);
}
if (!ReferenceEquals(baseAddress.Scheme, Uri.UriSchemeHttp) && !ReferenceEquals(baseAddress.Scheme, Uri.UriSchemeHttps))
{
throw Error.ArgumentUriNotHttpOrHttpsScheme("baseAddress", baseAddress);
}
return baseAddress;
}
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "We never want to fail here so we have to catch all exceptions.")]
private static int GetDefaultMaxConcurrentRequests()
{
try
{
return Math.Max(Environment.ProcessorCount * DefaultMaxConcurrentRequests, DefaultMaxConcurrentRequests);
}
catch
{
return DefaultMaxConcurrentRequests;
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,9 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Reflection;
using System.Runtime.CompilerServices;
[assembly: AssemblyTitle("System.Web.Http.SelfHost")]
[assembly: AssemblyDescription("")]
[assembly: InternalsVisibleTo("System.Web.Http.SelfHost.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")]
[assembly: InternalsVisibleTo("System.Web.Http.SelfHost.Test.Unit, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")]

View File

@ -0,0 +1,360 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.239
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace System.Web.Http.SelfHost.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class SRResources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal SRResources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("System.Web.Http.SelfHost.Properties.SRResources", typeof(SRResources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to End cannot be called twice on an AsyncResult..
/// </summary>
internal static string AsyncResultAlreadyEnded {
get {
return ResourceManager.GetString("AsyncResultAlreadyEnded", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The IAsyncResult implementation &apos;{0}&apos; tried to complete a single operation multiple times. This could be caused by an incorrect application IAsyncResult implementation or other extensibility code, such as an IAsyncResult that returns incorrect CompletedSynchronously values or invokes the AsyncCallback multiple times..
/// </summary>
internal static string AsyncResultCompletedTwice {
get {
return ResourceManager.GetString("AsyncResultCompletedTwice", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The size quota for this stream ({0}) has been exceeded..
/// </summary>
internal static string BufferedOutputStreamQuotaExceeded {
get {
return ResourceManager.GetString("BufferedOutputStreamQuotaExceeded", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The UseWindowsAuthentication option cannot be enabled when a UserNamePasswordValidator is specified on the HttpSelfHostConfiguration.&quot;.
/// </summary>
internal static string CannotUseWindowsAuthWithUserNamePasswordValidator {
get {
return ResourceManager.GetString("CannotUseWindowsAuthWithUserNamePasswordValidator", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Certificate-based client authentication is not supported in TransportCredentialOnly security mode. Select the Transport security mode..
/// </summary>
internal static string CertificateUnsupportedForHttpTransportCredentialOnly {
get {
return ResourceManager.GetString("CertificateUnsupportedForHttpTransportCredentialOnly", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The &apos;{0}&apos; type does not support building &apos;{1}&apos; instances..
/// </summary>
internal static string ChannelFactoryNotSupported {
get {
return ResourceManager.GetString("ChannelFactoryNotSupported", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The &apos;{0}&apos; type does not support the &apos;{1}&apos; channel shape. Implement the &apos;{2}&apos; channel shape to use this type..
/// </summary>
internal static string ChannelShapeNotSupported {
get {
return ResourceManager.GetString("ChannelShapeNotSupported", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The message version of the outgoing message ({0}) does not match that of the encoder ({1}). Make sure the binding is configured with the same version as the message..
/// </summary>
internal static string EncoderMessageVersionMismatch {
get {
return ResourceManager.GetString("EncoderMessageVersionMismatch", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The &apos;{0}&apos; type does not support a session encoder..
/// </summary>
internal static string HttpMessageEncoderFactoryDoesNotSupportSessionEncoder {
get {
return ResourceManager.GetString("HttpMessageEncoderFactoryDoesNotSupportSessionEncoder", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Could not obtain an HTTP request from message of type &apos;{0}&apos;..
/// </summary>
internal static string HttpMessageHandlerInvalidMessage {
get {
return ResourceManager.GetString("HttpMessageHandlerInvalidMessage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to This &apos;{0}&apos; instance has already been started once. To start another instance, please create a new &apos;{0}&apos; object and start that..
/// </summary>
internal static string HttpServerAlreadyRunning {
get {
return ResourceManager.GetString("HttpServerAlreadyRunning", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The inner listener factory of {0} must be set before this operation..
/// </summary>
internal static string InnerListenerFactoryNotSet {
get {
return ResourceManager.GetString("InnerListenerFactoryNotSet", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to An incorrect IAsyncResult was provided to an &apos;End&apos; method. The IAsyncResult object passed to &apos;End&apos; must be the one returned from the matching &apos;Begin&apos; or passed to the callback provided to &apos;Begin&apos;..
/// </summary>
internal static string InvalidAsyncResult {
get {
return ResourceManager.GetString("InvalidAsyncResult", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to An incorrect implementation of the IAsyncResult interface may be returning incorrect values from the CompletedSynchronously property or calling the AsyncCallback more than once. The type {0} could be the incorrect implementation..
/// </summary>
internal static string InvalidAsyncResultImplementation {
get {
return ResourceManager.GetString("InvalidAsyncResultImplementation", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to An incorrect implementation of the IAsyncResult interface may be returning incorrect values from the CompletedSynchronously property or calling the AsyncCallback more than once..
/// </summary>
internal static string InvalidAsyncResultImplementationGeneric {
get {
return ResourceManager.GetString("InvalidAsyncResultImplementationGeneric", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Error creating &apos;{0}&apos; instance using &apos;{1}&apos;..
/// </summary>
internal static string InvalidChannelListener {
get {
return ResourceManager.GetString("InvalidChannelListener", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to A null value was returned from an async &apos;Begin&apos; method or passed to an AsyncCallback. Async &apos;Begin&apos; implementations must return a non-null IAsyncResult and pass the same IAsyncResult object as the parameter to the AsyncCallback..
/// </summary>
internal static string InvalidNullAsyncResult {
get {
return ResourceManager.GetString("InvalidNullAsyncResult", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to HTTP request message body with a content length of &apos;{0}&apos; bytes..
/// </summary>
internal static string MessageBodyIsHttpRequestMessageWithKnownContentLength {
get {
return ResourceManager.GetString("MessageBodyIsHttpRequestMessageWithKnownContentLength", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to HTTP request message body with an undetermined content length..
/// </summary>
internal static string MessageBodyIsHttpRequestMessageWithUnknownContentLength {
get {
return ResourceManager.GetString("MessageBodyIsHttpRequestMessageWithUnknownContentLength", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to HTTP response message body with a content length of &apos;{0}&apos; bytes..
/// </summary>
internal static string MessageBodyIsHttpResponseMessageWithKnownContentLength {
get {
return ResourceManager.GetString("MessageBodyIsHttpResponseMessageWithKnownContentLength", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to HTTP response message body with an undetermined content length..
/// </summary>
internal static string MessageBodyIsHttpResponseMessageWithUnknownContentLength {
get {
return ResourceManager.GetString("MessageBodyIsHttpResponseMessageWithUnknownContentLength", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The &apos;{0}&apos; is closed and can no longer be used..
/// </summary>
internal static string MessageClosed {
get {
return ResourceManager.GetString("MessageClosed", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The response message is not valid for the encoder used by the &apos;{0}&apos; binding, which requires that the response message have been created with the &apos;{1}&apos; extension method on the &apos;{2}&apos; class..
/// </summary>
internal static string MessageInvalidForHttpMessageEncoder {
get {
return ResourceManager.GetString("MessageInvalidForHttpMessageEncoder", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The message instance does not support being read, written out or copied. Use the &apos;{0}&apos; or &apos;{1}&apos; extension methods on the &apos;{2}&apos; class to access the message content..
/// </summary>
internal static string MessageReadWriteCopyNotSupported {
get {
return ResourceManager.GetString("MessageReadWriteCopyNotSupported", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The message instance is non-empty but the &apos;{0}&apos; extension method on the &apos;{1}&apos; class returned null. Message instances that do not support the &apos;{0}&apos; extension method must be empty. .
/// </summary>
internal static string NonHttpMessageMustBeEmpty {
get {
return ResourceManager.GetString("NonHttpMessageMustBeEmpty", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Nonnegative number required.
/// </summary>
internal static string NonnegativeNumberRequired {
get {
return ResourceManager.GetString("NonnegativeNumberRequired", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The &apos;{0}&apos; type supports only MessageVersion.None. .
/// </summary>
internal static string OnlyMessageVersionNoneSupportedOnHttpMessageEncodingBindingElement {
get {
return ResourceManager.GetString("OnlyMessageVersionNoneSupportedOnHttpMessageEncodingBindingElement", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The value of the &apos;{0}&apos; parameter must be less than or equal to the value of the &apos;{1}&apos; parameter..
/// </summary>
internal static string ParameterMustBeLessThanOrEqualSecondParameter {
get {
return ResourceManager.GetString("ParameterMustBeLessThanOrEqualSecondParameter", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Read not supported on this stream..
/// </summary>
internal static string ReadNotSupported {
get {
return ResourceManager.GetString("ReadNotSupported", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The incoming message does not have the required &apos;{0}&apos; property of type &apos;{1}&apos;..
/// </summary>
internal static string RequestMissingHttpRequestMessageProperty {
get {
return ResourceManager.GetString("RequestMissingHttpRequestMessageProperty", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The incoming message does not have the required &apos;To&apos; header..
/// </summary>
internal static string RequestMissingToHeader {
get {
return ResourceManager.GetString("RequestMissingToHeader", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Seek not supported on this stream..
/// </summary>
internal static string SeekNotSupported {
get {
return ResourceManager.GetString("SeekNotSupported", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Value must be non-negative..
/// </summary>
internal static string ValueMustBeNonNegative {
get {
return ResourceManager.GetString("ValueMustBeNonNegative", resourceCulture);
}
}
}
}

View File

@ -0,0 +1,219 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AsyncResultAlreadyEnded" xml:space="preserve">
<value>End cannot be called twice on an AsyncResult.</value>
</data>
<data name="AsyncResultCompletedTwice" xml:space="preserve">
<value>The IAsyncResult implementation '{0}' tried to complete a single operation multiple times. This could be caused by an incorrect application IAsyncResult implementation or other extensibility code, such as an IAsyncResult that returns incorrect CompletedSynchronously values or invokes the AsyncCallback multiple times.</value>
</data>
<data name="CannotUseWindowsAuthWithUserNamePasswordValidator" xml:space="preserve">
<value>The UseWindowsAuthentication option cannot be enabled when a UserNamePasswordValidator is specified on the HttpSelfHostConfiguration."</value>
</data>
<data name="CertificateUnsupportedForHttpTransportCredentialOnly" xml:space="preserve">
<value>Certificate-based client authentication is not supported in TransportCredentialOnly security mode. Select the Transport security mode.</value>
</data>
<data name="ChannelFactoryNotSupported" xml:space="preserve">
<value>The '{0}' type does not support building '{1}' instances.</value>
</data>
<data name="ChannelShapeNotSupported" xml:space="preserve">
<value>The '{0}' type does not support the '{1}' channel shape. Implement the '{2}' channel shape to use this type.</value>
</data>
<data name="EncoderMessageVersionMismatch" xml:space="preserve">
<value>The message version of the outgoing message ({0}) does not match that of the encoder ({1}). Make sure the binding is configured with the same version as the message.</value>
</data>
<data name="HttpMessageEncoderFactoryDoesNotSupportSessionEncoder" xml:space="preserve">
<value>The '{0}' type does not support a session encoder.</value>
</data>
<data name="HttpMessageHandlerInvalidMessage" xml:space="preserve">
<value>Could not obtain an HTTP request from message of type '{0}'.</value>
</data>
<data name="HttpServerAlreadyRunning" xml:space="preserve">
<value>This '{0}' instance has already been started once. To start another instance, please create a new '{0}' object and start that.</value>
</data>
<data name="InnerListenerFactoryNotSet" xml:space="preserve">
<value>The inner listener factory of {0} must be set before this operation.</value>
</data>
<data name="InvalidAsyncResult" xml:space="preserve">
<value>An incorrect IAsyncResult was provided to an 'End' method. The IAsyncResult object passed to 'End' must be the one returned from the matching 'Begin' or passed to the callback provided to 'Begin'.</value>
</data>
<data name="InvalidAsyncResultImplementation" xml:space="preserve">
<value>An incorrect implementation of the IAsyncResult interface may be returning incorrect values from the CompletedSynchronously property or calling the AsyncCallback more than once. The type {0} could be the incorrect implementation.</value>
</data>
<data name="InvalidAsyncResultImplementationGeneric" xml:space="preserve">
<value>An incorrect implementation of the IAsyncResult interface may be returning incorrect values from the CompletedSynchronously property or calling the AsyncCallback more than once.</value>
</data>
<data name="InvalidChannelListener" xml:space="preserve">
<value>Error creating '{0}' instance using '{1}'.</value>
</data>
<data name="InvalidNullAsyncResult" xml:space="preserve">
<value>A null value was returned from an async 'Begin' method or passed to an AsyncCallback. Async 'Begin' implementations must return a non-null IAsyncResult and pass the same IAsyncResult object as the parameter to the AsyncCallback.</value>
</data>
<data name="MessageBodyIsHttpRequestMessageWithKnownContentLength" xml:space="preserve">
<value>HTTP request message body with a content length of '{0}' bytes.</value>
</data>
<data name="MessageBodyIsHttpRequestMessageWithUnknownContentLength" xml:space="preserve">
<value>HTTP request message body with an undetermined content length.</value>
</data>
<data name="MessageBodyIsHttpResponseMessageWithKnownContentLength" xml:space="preserve">
<value>HTTP response message body with a content length of '{0}' bytes.</value>
</data>
<data name="MessageBodyIsHttpResponseMessageWithUnknownContentLength" xml:space="preserve">
<value>HTTP response message body with an undetermined content length.</value>
</data>
<data name="MessageClosed" xml:space="preserve">
<value>The '{0}' is closed and can no longer be used.</value>
</data>
<data name="MessageInvalidForHttpMessageEncoder" xml:space="preserve">
<value>The response message is not valid for the encoder used by the '{0}' binding, which requires that the response message have been created with the '{1}' extension method on the '{2}' class.</value>
</data>
<data name="MessageReadWriteCopyNotSupported" xml:space="preserve">
<value>The message instance does not support being read, written out or copied. Use the '{0}' or '{1}' extension methods on the '{2}' class to access the message content.</value>
</data>
<data name="NonHttpMessageMustBeEmpty" xml:space="preserve">
<value>The message instance is non-empty but the '{0}' extension method on the '{1}' class returned null. Message instances that do not support the '{0}' extension method must be empty. </value>
</data>
<data name="NonnegativeNumberRequired" xml:space="preserve">
<value>Nonnegative number required</value>
</data>
<data name="OnlyMessageVersionNoneSupportedOnHttpMessageEncodingBindingElement" xml:space="preserve">
<value>The '{0}' type supports only MessageVersion.None. </value>
</data>
<data name="ParameterMustBeLessThanOrEqualSecondParameter" xml:space="preserve">
<value>The value of the '{0}' parameter must be less than or equal to the value of the '{1}' parameter.</value>
</data>
<data name="RequestMissingHttpRequestMessageProperty" xml:space="preserve">
<value>The incoming message does not have the required '{0}' property of type '{1}'.</value>
</data>
<data name="RequestMissingToHeader" xml:space="preserve">
<value>The incoming message does not have the required 'To' header.</value>
</data>
<data name="BufferedOutputStreamQuotaExceeded" xml:space="preserve">
<value>The size quota for this stream ({0}) has been exceeded.</value>
</data>
<data name="ReadNotSupported" xml:space="preserve">
<value>Read not supported on this stream.</value>
</data>
<data name="SeekNotSupported" xml:space="preserve">
<value>Seek not supported on this stream.</value>
</data>
<data name="ValueMustBeNonNegative" xml:space="preserve">
<value>Value must be non-negative.</value>
</data>
</root>

View File

@ -0,0 +1,348 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Threading;
using System.Web.Http.SelfHost.Properties;
namespace System.Web.Http.SelfHost.ServiceModel.Channels
{
// AsyncResult starts acquired; Complete releases.
[SuppressMessage("Microsoft.Design", "CA1001:TypesThatOwnDisposableFieldsShouldBeDisposable", Justification = "Ported from WCF")]
internal abstract class AsyncResult : IAsyncResult
{
private static AsyncCallback _asyncCompletionWrapperCallback;
private readonly AsyncCallback _completionCallback;
private bool _completedSynchronously;
private bool _endCalled;
private Exception _exception;
private bool _isCompleted;
private AsyncCompletion _nextAsyncCompletion;
private readonly object _state;
private Action _beforePrepareAsyncCompletionAction;
private Func<IAsyncResult, bool> _checkSyncValidationFunc;
private ManualResetEvent _manualResetEvent;
private readonly object _manualResetEventLock = new object();
protected AsyncResult(AsyncCallback callback, object state)
{
_completionCallback = callback;
_state = state;
}
/// <summary>
/// Can be utilized by subclasses to write core completion code for both the sync and async paths
/// in one location, signalling chainable synchronous completion with the boolean result,
/// and leveraging PrepareAsyncCompletion for conversion to an AsyncCallback.
/// </summary>
/// <remarks>NOTE: requires that "this" is passed in as the state object to the asynchronous sub-call being used with a completion routine.</remarks>
protected delegate bool AsyncCompletion(IAsyncResult result);
public object AsyncState
{
get { return _state; }
}
public WaitHandle AsyncWaitHandle
{
get
{
lock (_manualResetEventLock)
{
if (_manualResetEvent == null)
{
_manualResetEvent = new ManualResetEvent(_isCompleted);
}
}
return _manualResetEvent;
}
}
public bool CompletedSynchronously
{
get { return _completedSynchronously; }
}
public bool HasCallback
{
get { return _completionCallback != null; }
}
public bool IsCompleted
{
get { return _isCompleted; }
}
// used in conjunction with PrepareAsyncCompletion to allow for finally blocks
protected Action<AsyncResult, Exception> OnCompleting { get; set; }
// subclasses like TraceAsyncResult can use this to wrap the callback functionality in a scope
protected Action<AsyncCallback, IAsyncResult> VirtualCallback { get; set; }
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Exception is propagated or FailFast")]
protected void Complete(bool didCompleteSynchronously)
{
if (_isCompleted)
{
throw Error.InvalidOperation(SRResources.AsyncResultCompletedTwice, GetType());
}
_completedSynchronously = didCompleteSynchronously;
if (OnCompleting != null)
{
// Allow exception replacement, like a catch/throw pattern.
try
{
OnCompleting(this, _exception);
}
catch (Exception e)
{
_exception = e;
}
}
if (didCompleteSynchronously)
{
// If we completedSynchronously, then there's no chance that the manualResetEvent was created so
// we don't need to worry about a race
Debug.Assert(_manualResetEvent == null, "No ManualResetEvent should be created for a synchronous AsyncResult.");
_isCompleted = true;
}
else
{
lock (_manualResetEventLock)
{
_isCompleted = true;
if (_manualResetEvent != null)
{
_manualResetEvent.Set();
}
}
}
if (_completionCallback != null)
{
try
{
if (VirtualCallback != null)
{
VirtualCallback(_completionCallback, this);
}
else
{
_completionCallback(this);
}
}
#pragma warning disable 1634
#pragma warning suppress 56500 // transferring exception to another thread
catch (Exception e)
{
// String is not resourced because it occurs only in debug build, only with a fatal assert,
// and because it appears as an unused resource in a release build
Contract.Assert(false, Error.Format("{0}{1}{2}", "Async Callback threw an exception.", Environment.NewLine, e.ToString()));
}
#pragma warning restore 1634
}
}
protected void Complete(bool didCompleteSynchronously, Exception error)
{
_exception = error;
Complete(didCompleteSynchronously);
}
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Exception is propagated")]
private static void AsyncCompletionWrapperCallback(IAsyncResult result)
{
if (result == null)
{
throw Error.InvalidOperation(SRResources.InvalidNullAsyncResult);
}
if (result.CompletedSynchronously)
{
return;
}
AsyncResult thisPtr = (AsyncResult)result.AsyncState;
if (!thisPtr.OnContinueAsyncCompletion(result))
{
return;
}
AsyncCompletion callback = thisPtr.GetNextCompletion();
if (callback == null)
{
ThrowInvalidAsyncResult(result);
}
bool completeSelf = false;
Exception completionException = null;
try
{
completeSelf = callback(result);
}
catch (Exception e)
{
completeSelf = true;
completionException = e;
}
if (completeSelf)
{
thisPtr.Complete(false, completionException);
}
}
// Note: this should be only derived by the TransactedAsyncResult
protected virtual bool OnContinueAsyncCompletion(IAsyncResult result)
{
return true;
}
// Note: this should be used only by the TransactedAsyncResult
protected void SetBeforePrepareAsyncCompletionAction(Action completionAction)
{
_beforePrepareAsyncCompletionAction = completionAction;
}
// Note: this should be used only by the TransactedAsyncResult
protected void SetCheckSyncValidationFunc(Func<IAsyncResult, bool> validationFunc)
{
_checkSyncValidationFunc = validationFunc;
}
protected AsyncCallback PrepareAsyncCompletion(AsyncCompletion callback)
{
if (_beforePrepareAsyncCompletionAction != null)
{
_beforePrepareAsyncCompletionAction();
}
_nextAsyncCompletion = callback;
if (AsyncResult._asyncCompletionWrapperCallback == null)
{
AsyncResult._asyncCompletionWrapperCallback = new AsyncCallback(AsyncCompletionWrapperCallback);
}
return AsyncResult._asyncCompletionWrapperCallback;
}
protected bool CheckSyncContinue(IAsyncResult result)
{
AsyncCompletion dummy;
return TryContinueHelper(result, out dummy);
}
protected bool SyncContinue(IAsyncResult result)
{
AsyncCompletion callback;
if (TryContinueHelper(result, out callback))
{
return callback(result);
}
else
{
return false;
}
}
private bool TryContinueHelper(IAsyncResult result, out AsyncCompletion callback)
{
if (result == null)
{
throw Error.InvalidOperation(SRResources.InvalidNullAsyncResult);
}
callback = null;
if (_checkSyncValidationFunc != null)
{
if (!_checkSyncValidationFunc(result))
{
return false;
}
}
else if (!result.CompletedSynchronously)
{
return false;
}
callback = GetNextCompletion();
if (callback == null)
{
ThrowInvalidAsyncResult("Only call Check/SyncContinue once per async operation (once per PrepareAsyncCompletion).");
}
return true;
}
private AsyncCompletion GetNextCompletion()
{
AsyncCompletion result = _nextAsyncCompletion;
_nextAsyncCompletion = null;
return result;
}
protected static void ThrowInvalidAsyncResult(IAsyncResult result)
{
if (result == null)
{
throw Error.ArgumentNull("result");
}
throw Error.InvalidOperation(SRResources.InvalidAsyncResultImplementation, result.GetType());
}
protected static void ThrowInvalidAsyncResult(string debugText)
{
string message = SRResources.InvalidAsyncResultImplementationGeneric;
if (debugText != null)
{
#if DEBUG
message += " " + debugText;
#endif
}
throw Error.InvalidOperation(message);
}
[SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "Existing API")]
protected static TAsyncResult End<TAsyncResult>(IAsyncResult result)
where TAsyncResult : AsyncResult
{
if (result == null)
{
throw Error.ArgumentNull("result");
}
TAsyncResult asyncResult = result as TAsyncResult;
if (asyncResult == null)
{
throw Error.Argument("result", SRResources.InvalidAsyncResult);
}
if (asyncResult._endCalled)
{
throw Error.InvalidOperation(SRResources.AsyncResultAlreadyEnded);
}
asyncResult._endCalled = true;
if (!asyncResult._isCompleted)
{
asyncResult.AsyncWaitHandle.WaitOne();
}
if (asyncResult._manualResetEvent != null)
{
asyncResult._manualResetEvent.Close();
}
if (asyncResult._exception != null)
{
throw asyncResult._exception;
}
return asyncResult;
}
}
}

View File

@ -0,0 +1,34 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.ServiceModel;
using System.ServiceModel.Channels;
namespace System.Web.Http.SelfHost.ServiceModel.Channels
{
internal class BufferManagerOutputStream : BufferedOutputStream
{
private readonly string _quotaExceededString;
public BufferManagerOutputStream(string quotaExceededString, int initialSize, int maxSize, BufferManager bufferManager)
: base(initialSize, maxSize, bufferManager)
{
_quotaExceededString = quotaExceededString;
}
public void Init(int initialSize, int maxSizeQuota, BufferManager bufferManager)
{
Init(initialSize, maxSizeQuota, maxSizeQuota, bufferManager);
}
public void Init(int initialSize, int maxSizeQuota, int effectiveMaxSize, BufferManager bufferManager)
{
Reinitialize(initialSize, maxSizeQuota, effectiveMaxSize, bufferManager);
}
protected override Exception CreateQuotaExceededException(int maxSizeQuota)
{
string excMsg = Error.Format(_quotaExceededString, maxSizeQuota);
return new QuotaExceededException(excMsg);
}
}
}

Some files were not shown because too many files have changed in this diff Show More