Self Host模式下的ASP.NET Web API与WCF非常相似,都可以寄宿在任意类型的托管应用程序中,宿主可以是Windows Form 、WPF、控制台应用以及Windows Service,寄宿的请求的监听、接收 和响应功能,是通过一个类型为HttpBinding的Binding对象创建的ChannelListener管道来完成的。

一、Binding绑定模型

  Binding用来创建处理和传输消息的信道栈,信道栈有一组Channel组成,Binding也由一组BindingElement组成,每个BindingElement会创建一个ChannelListener,ChannelListener再创建对应的Channel,而每个Channel负责处理消息的单独一块功能,Binding启动时候会创建多个Channel组成一个消息处理管道,对请求依次进行处理,对相应按相反方向进行处理,有点类似ASP.NET Web API的消息处理管道,而这是宿主内部的功能,要注意区分。

  对于这种由Binding创建的多个Channel组成的消息处理管道的消息处理能力,是由其包含的Channel决定的,有两种Channel是必不可少的,TransportChannel和MessageEncodingChanneI:

  • TransportChannel  面向传输层用于发送和接收消息
  • MessageEncodingChanneI 负责对接收(请求)的消息实施解码 ,并对发送(响应)的消息实施编码

二、涉及的类及源码分析

  类主要在程序集System.Web.Http SeIfHost.dII中。

  

  

1、HttpBinding

  继承自Binding,其只由两个BindingElement组成,Http(s)TransportBindingElement和HttpMessageEncodingBindingElement

  Http(s)TransportBindingElement  决定最终采用的传输协议,Http或Https

  HttpMessageEncodingBindingElement  创 建一个MessageEncoder对象完成针对消息的编码/解码工作 。

  public class  HttpBinding : Binding, IBindingRuntimePreferences
  {
    internal const string CollectionElementName = "httpBinding";

    //默认传输模式为Buffered
    internal const  TransferMode DefaultTransferMode = System.ServiceModel.TransferMode.Buffered;
    //传输BindingElement 
    private HttpsTransportBindingElement _httpsTransportBindingElement;
    private HttpTransportBindingElement _httpTransportBindingElement;
    private HttpBindingSecurity _security;

    //编码/解码BindingElement
    private HttpMessageEncodingBindingElement _httpMessageEncodingBindingElement;
    private Action<HttpTransportBindingElement> _configureTransportBindingElement;

    //初始化HttpBinding 
    public HttpBinding()
    {
      Initialize();
    }

    public HttpBinding(HttpBindingSecurityMode securityMode)
    : this()
    {
      _security.Mode = securityMode;
    }

    //从URL中确定主机名的比较模式

    public  HostNameComparisonMode HostNameComparisonMode

    {
      get { return _httpTransportBindingElement.HostNameComparisonMode; }

      set
      {
        _httpTransportBindingElement.HostNameComparisonMode = value;
        _httpsTransportBindingElement.HostNameComparisonMode = value;
     }
    }

 
    public long MaxBufferPoolSize
    {
      get { return _httpTransportBindingElement.MaxBufferPoolSize; }

      set
      {
        _httpTransportBindingElement.MaxBufferPoolSize = value;
        _httpsTransportBindingElement.MaxBufferPoolSize = value;
      }
    }

    //Buffered模式下的消息的最大缓冲区大小,Buffered模式,即消息先会保存于内存缓冲区后一并传输
    [DefaultValue(TransportDefaults.MaxBufferSize)]
    public int MaxBufferSize
    {
      get { return _httpTransportBindingElement.MaxBufferSize; }

      set
      {
        _httpTransportBindingElement.MaxBufferSize = value;
        _httpsTransportBindingElement.MaxBufferSize = value;
      }
    }

    //请求消息的最大尺寸,默认为65536
    [DefaultValue(TransportDefaults.MaxReceivedMessageSize)]
    public long MaxReceivedMessageSize
    {
      get { return _httpTransportBindingElement.MaxReceivedMessageSize; }

      set
      {
        _httpTransportBindingElement.MaxReceivedMessageSize = value;
        _httpsTransportBindingElement.MaxReceivedMessageSize = value;
      }
    }

    public Action<HttpTransportBindingElement> ConfigureTransportBindingElement
    {
      get { return _configureTransportBindingElement; }

      set
      {
        if (value == null)
        {
          throw Error.PropertyNull();
        }

        _configureTransportBindingElement = value;
      }
    }

    //传输模式

    [DefaultValue(HttpTransportDefaults.TransferMode)]
    public TransferMode TransferMode
    {
      get { return _httpTransportBindingElement.TransferMode; }

      set
      {
        _httpTransportBindingElement.TransferMode = value;
        _httpsTransportBindingElement.TransferMode = value;
      }
    }

    //创建BindingElements,只包含两种
    public override BindingElementCollection CreateBindingElements()
    {
      BindingElementCollection bindingElements = new BindingElementCollection();

      bindingElements.Add(_httpMessageEncodingBindingElement);
      bindingElements.Add(GetTransport());

      return bindingElements.Clone();
    }

    private TransportBindingElement GetTransport()
    {
      HttpTransportBindingElement result = null;

      if (_security.Mode == HttpBindingSecurityMode.Transport)
      {
        _security.Transport.ConfigureTransportProtectionAndAuthentication(_httpsTransportBindingElement);
        result = _httpsTransportBindingElement;
      }
      else if (_security.Mode == HttpBindingSecurityMode.TransportCredentialOnly)
      {
        _security.Transport.ConfigureTransportAuthentication(_httpTransportBindingElement);
        result = _httpTransportBindingElement;
      }
      else
      {
        _security.Transport.DisableTransportAuthentication(_httpTransportBindingElement);
        result = _httpTransportBindingElement;
      }

      if (_configureTransportBindingElement != null)
      {
        _configureTransportBindingElement(result);
      }

      return result;
    }

    //初始化各种对象

    private void Initialize()
    {
      _security = new  HttpBindingSecurity();

      _httpTransportBindingElement = new HttpTransportBindingElement();
      _httpTransportBindingElement.ManualAddressing = true;

      _httpsTransportBindingElement = new HttpsTransportBindingElement();
      _httpsTransportBindingElement.ManualAddressing = true;

      _httpMessageEncodingBindingElement = new HttpMessageEncodingBindingElement();
    }
  }

2、HttpMessage

  Binding处理管道中处理的消息是HttpMessage,其继承自Message,它是对ASP.NET Web API处理的消息HttpRequestMessage和HttpResponseMessage的封装;HttpMessageEncoder对请求消息解码后得到HttpMessage对象,其会转成—个HttpRequestMessage对象并传入ASP.NET WebAPI消息处理管道进行处理,处理完后返回HttpResponseMessage对象,其被封装成HttpMessage对象,在通过传输层将响应返回给客户端之前,需要利用HttpMessageEncoder对其进行编码,然后进行传输。

  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; }

    //从HttpMessage中获取HttpRequestMessage,参数extract是否是抽取,抽取即访问一次后第二次访问会返回null

    public HttpRequestMessage GetHttpRequestMessage(bool extract)
    {
      EnsureNotDisposed();
      Contract.Assert(IsRequest, "This method should only be called when IsRequest is true.");
      if (extract)
      {
        HttpRequestMessage req = _request;

        //设置为null,第二次访问为null
        _request = null;
        return req;
      }

      return _request;
    }

    //从HttpMessage中获取HttpResponseMessage ,参数extract是否是抽取,抽取即访问一次后第二次访问会返回null

    public HttpResponseMessage GetHttpResponseMessage(bool extract)
    {
      EnsureNotDisposed();
      Contract.Assert(!IsRequest, "This method should only be called when IsRequest is false.");
      if (extract)
      {
        HttpResponseMessage res = _response;

        //设置为null,第二次访问为null
        _response = null;
        return res;
      }

      return _response;
    }

    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;
    }
  }

3、HttpSelfHostServer

  继承自HttpServer,是WebAPI 消息处理管道的第一个处理器,类似Web Host模式,管道的配置是通过HttpConfiguration完成,其对应由HttpSelfHostConfiguration来完成,也是在构造函数里指定。

  重要逻辑都在代码注释里,代码太多,只是拿出重要的代码,以下是注意点:

  • 虽然继承HttpServer,但是没有重写SendAsync方法,只是重用了HttpServer的SendAsync,所以这部分逻辑是一致的
  • HttpSelfHostServer本身会打开和开启channel来监听,监听到消息后,会创建HttpRequestMessage,并调用基类HttpServer的SendAsync,进行后续的消息处理,返回响应HttpResponseMessage后,转换成Message返回给客户端。

  public sealed class  HttpSelfHostServer : HttpServer
  {
    private ConcurrentBag<IReplyChannel> _channels = new ConcurrentBag<IReplyChannel>();
    private CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();

    private bool _disposed;
    private HttpSelfHostConfiguration _configuration;
    private IChannelListener<IReplyChannel> _listener;

    private readonly object _windowSizeLock = new object();

    //调用基类HttpServer构造函数,所以最有一个处理器默认也是HttpRoutingDispatcher
    public HttpSelfHostServer(HttpSelfHostConfiguration configuration)
    : base(configuration)
    {
      if (configuration == null)
      {
        throw Error.ArgumentNull("configuration");
      }

      _configuration = configuration;
      InitializeCallbacks();
    }

    //初始化回调,接受到消息后,通过回调触发
    private void InitializeCallbacks()
    {
      //...
      _onReceiveRequestContextComplete = new AsyncCallback(OnReceiveRequestContextComplete);
      _onReplyComplete = new AsyncCallback(OnReplyComplete);

    }

    //打开服务
    public Task OpenAsync()
    {
      if (Interlocked.CompareExchange(ref _state, 1, 0) == 1)
      {
        throw Error.InvalidOperation(SRResources.HttpServerAlreadyRunning, typeof(HttpSelfHostServer).Name);
      }

      _openTaskCompletionSource = new TaskCompletionSource<bool>();
      BeginOpenListener(this);
      return _openTaskCompletionSource.Task;
    }

    private void BeginOpenListener(HttpSelfHostServer server)
    {
      Contract.Assert(server != null);

      try
      {
        // 创建 WCF HTTP transport channel
        HttpBinding binding = new HttpBinding();

        // 获取配置(从HttpSelfHostConfiguration ),并设置到HttpBinding 
        BindingParameterCollection bindingParameters = server._configuration.ConfigureBinding(binding);
        if (bindingParameters == null)
        {
          bindingParameters = new BindingParameterCollection();
        }

        // 创建channel listener
        server._listener = binding.BuildChannelListener<IReplyChannel>(server._configuration.BaseAddress, bindingParameters);
        if (server._listener == null)
        {
          throw Error.InvalidOperation(SRResources.InvalidChannelListener, typeof(IChannelListener).Name, typeof(IReplyChannel).Name);
        }

        //开始监听

        IAsyncResult result = server._listener.BeginOpen(_onOpenListenerComplete, server);
        if (result.CompletedSynchronously)
        {

          //监听到请求消息,触发回调函数
          OpenListenerComplete(result);
        }
      }
      catch (Exception e)
      {
        FaultTask(server._openTaskCompletionSource, e);
      }
    }

    //..省略各种回调

    //Channel接收到消息后,通过回调最后会调用此方法
    private async void ProcessRequestContext(ChannelContext channelContext, RequestContext requestContext)
    {
      Contract.Assert(channelContext != null);
      Contract.Assert(requestContext != null);

      //调用下边的核心方法SendAsync

      HttpResponseMessage response = await SendAsync(channelContext, requestContext);

      //异步调用处理完后返回响应消息,把响应消息转换成Message 
      Message reply = response.ToMessage();

      //传回给客户端
      BeginReply(new ReplyContext(channelContext, requestContext, reply));
    }

    //核心方法,注意没有重写(override)基类SendAsync

    private async  Task<HttpResponseMessage> SendAsync(ChannelContext channelContext, RequestContext requestContext)
    {
      HttpRequestMessage request = null;
      try
      {
        request = CreateHttpRequestMessage(requestContext);
      }
      catch
      {
        return new HttpResponseMessage(HttpStatusCode.BadRequest);
      }

      try
      {

        //SendAsync方法是HttpServer的SendAsync,因为本类HttpSelfHostServer没有override该方法,

        //所以其他逻辑,比如建立Web API消息处理管道等,都和HttpServer一样
        HttpResponseMessage response = await channelContext.Server.SendAsync(request, channelContext.Server._cancellationTokenSource.Token);

        if (response == null)
        {
          response = request.CreateResponse(HttpStatusCode.InternalServerError);
        }

        return response;
      }
      catch (OperationCanceledException operationCanceledException)
      {
        return request.CreateErrorResponse(HttpStatusCode.ServiceUnavailable, SRResources.RequestCancelled, operationCanceledException);
      }
    }

    //构建HttpRequestMessage

    private  HttpRequestMessage CreateHttpRequestMessage(RequestContext requestContext)
    {
      // 从HTTP请求中获取 WCF Message
      HttpRequestMessage request = requestContext.RequestMessage.ToHttpRequestMessage();
      if (request == null)
      {
        throw Error.InvalidOperation(SRResources.HttpMessageHandlerInvalidMessage, requestContext.RequestMessage.GetType());
      }

      // 创建windows授权的 principal 信息并添加进请求HttpRequestMessage 
      SetCurrentPrincipal(request);

      HttpRequestContext httpRequestContext = new SelfHostHttpRequestContext(requestContext, _configuration,
      request);
      request.SetRequestContext(httpRequestContext);

      // 添加查询客户端证书委托到属性字典中,以便以后可以查询
      request.Properties.Add(HttpPropertyKeys.RetrieveClientCertificateDelegateKey, _retrieveClientCertificate);

      // 添加表示是否是本地请求信息到请求的属性字典中
      request.Properties.Add(HttpPropertyKeys.IsLocalKey, new Lazy<bool>(() => IsLocal(requestContext.RequestMessage)));
      return request;
    }

    protected override void Dispose(bool disposing)
    {
      if (!_disposed)
      {
        _disposed = true;
        if (_cancellationTokenSource != null)
        {
          _cancellationTokenSource.Dispose();
          _cancellationTokenSource = null;
        }
      }

      base.Dispose(disposing);
    }

    private static void SetCurrentPrincipal(HttpRequestMessage request)
    {
      SecurityMessageProperty property = request.GetSecurityMessageProperty();
      if (property != null)
      {
        ServiceSecurityContext context = property.ServiceSecurityContext;
        if (context != null && context.PrimaryIdentity != null)
        {
          WindowsIdentity windowsIdentity = context.PrimaryIdentity as WindowsIdentity;

          if (windowsIdentity != null)
          {

            //设置Thread.CurrentPrincipal 为WindowsPrincipal
            Thread.CurrentPrincipal = new WindowsPrincipal(windowsIdentity);
          }
        }
      }

    }
  }

4、HttpSelfHostConfiguration

  继承自HttpConfiguration,构造函数中指定一个Uri作为监听基地址,Self Host模式下,请求的监听、接收、响应基本都是通过HttpBinding完成的,HttpSelfHostConfiguration的大部分属性都是用于对创建HttpBinding进行配置,所以它们的属性基本相同。

  public class  HttpSelfHostConfiguration : HttpConfiguration
  {
    public HttpSelfHostConfiguration(string baseAddress)
    : this(CreateBaseAddress(baseAddress))
    {
    }

    //基地址Uri
    public Uri BaseAddress
    {
      get { return _baseAddress; }
    }

    //最大请求并发量,默认值是100,若是多处理器,要cheny乘以处理器个数
    public int MaxConcurrentRequests
    {
      get { return _maxConcurrentRequests; }

      set
      {
        if (value < MinConcurrentRequests)
        {
          throw Error.ArgumentMustBeGreaterThanOrEqualTo("value", value, MinConcurrentRequests);
        }
        _maxConcurrentRequests = value;
      }
    }

    //消息传输模式,分Streamed和Buffered(默认)
    public TransferMode TransferMode
    {
      get { return _transferMode; }

      set
      {
        TransferModeHelper.Validate(value, "value");
        _transferMode = value;
      }
    }

    //从URI中获取主机名的匹配比较模式
    public HostNameComparisonMode HostNameComparisonMode
    {
      get { return _hostNameComparisonMode; }

      set
      {
        HostNameComparisonModeHelper.Validate(value, "value");
        _hostNameComparisonMode = value;
      }
    }

    //Buffered模式的最大缓冲池大小,默认值65536

    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.ArgumentMustBeGreaterThanOrEqualTo("value", value, MinBufferSize);
        }
        _maxBufferSizeIsInitialized = true;
        _maxBufferSize = value;
      }
    }

    //允许请求消息的最大大小,默认为65536

    public long MaxReceivedMessageSize
    {
      get { return _maxReceivedMessageSize; }

      set
      {
        if (value < MinReceivedMessageSize)
        {
          throw Error.ArgumentMustBeGreaterThanOrEqualTo("value", value, MinReceivedMessageSize);
        }
        _maxReceivedMessageSize = value;
      }
    }

    //接收请求消息的超时时间,默认为10分钟  

    public TimeSpan ReceiveTimeout
    {
      get { return _receiveTimeout; }

      set
      {
        if (value < TimeSpan.Zero)
        {
          throw Error.ArgumentMustBeGreaterThanOrEqualTo("value", value, TimeSpan.Zero);
        }

        _receiveTimeout = value;
      }
    }

    //发送响应消息的超时时间,默认为1分钟  

    public TimeSpan SendTimeout
    {
      get { return _sendTimeout; }

      set
      {
        if (value < TimeSpan.Zero)
        {
          throw Error.ArgumentMustBeGreaterThanOrEqualTo("value", value, TimeSpan.Zero);
        }

        _sendTimeout = value;
      }
    }

    //客户端采用的用户凭证类型
    public HttpClientCredentialType ClientCredentialType
    {
      get { return _clientCredentialType; }
      set { _clientCredentialType = value; }
    }

    //将配置应用到httpBinding
    internal BindingParameterCollection ConfigureBinding(HttpBinding httpBinding)
    {
      return OnConfigureBinding(httpBinding);
    }

    
    protected virtual BindingParameterCollection OnConfigureBinding(HttpBinding httpBinding)
    {
      if (httpBinding == null)
      {
        throw Error.ArgumentNull("httpBinding");
      }

      if (_clientCredentialType != HttpClientCredentialType.Basic && _credentials.UserNameAuthentication.CustomUserNamePasswordValidator != null)
      {
        throw Error.InvalidOperation(SRResources.CannotUseOtherClientCredentialTypeWithUserNamePasswordValidator);
      }

      if (_clientCredentialType != HttpClientCredentialType.Certificate && _credentials.ClientCertificate.Authentication.CustomCertificateValidator != null)
      {
        throw Error.InvalidOperation(SRResources.CannotUseOtherClientCredentialTypeWithX509CertificateValidator);
      }

      httpBinding.MaxBufferSize = MaxBufferSize;
      httpBinding.MaxReceivedMessageSize = MaxReceivedMessageSize;
      httpBinding.TransferMode = TransferMode;
      httpBinding.HostNameComparisonMode = HostNameComparisonMode;
      httpBinding.ReceiveTimeout = ReceiveTimeout;
      httpBinding.SendTimeout = SendTimeout;

      if (_baseAddress.Scheme == Uri.UriSchemeHttps)
      {

        httpBinding.Security = new HttpBindingSecurity()
        {
          Mode = HttpBindingSecurityMode.Transport,
        };
      }

      if (_clientCredentialType != HttpClientCredentialType.None)
      {
        if (httpBinding.Security == null || httpBinding.Security.Mode == HttpBindingSecurityMode.None)
        {
          // Basic over HTTP case
          httpBinding.Security = new HttpBindingSecurity()
          {
            Mode = HttpBindingSecurityMode.TransportCredentialOnly,
          };
        }

        httpBinding.Security.Transport.ClientCredentialType = _clientCredentialType;
      }

      if (UserNamePasswordValidator != null || X509CertificateValidator != null)
      {
        // those are the only two things that affect service credentials
        return AddCredentialsToBindingParameters();
      }
      else
      {
        return null;
      }
    }

    private BindingParameterCollection AddCredentialsToBindingParameters()
    {
      BindingParameterCollection bindingParameters = new BindingParameterCollection();
      bindingParameters.Add(_credentials);
      return bindingParameters;
    }

    //根据基地址创建对应Uri

    private static Uri CreateBaseAddress(string baseAddress)
    {
      if (baseAddress == null)
      {
        throw Error.ArgumentNull("baseAddress");
      }

      return new Uri(baseAddress, UriKind.RelativeOrAbsolute);
    }
  }

三、HttpBiding、HttpSelfHostServer和消息处理管道的衔接

  先根据指定的监听基地址创建一个HttpSelftHostConfiguration对象,然后,根据它创建HttpSelfHostServer,调用OpenAsync方法开启时候,HttpSelfHostServer会创建一个HttpBinding,并用指定的HttpSelfHostConfiguration对HttpBinding进行配置,然后,HttpBinding会根据监听基地址创建一个ChannelListener管道,对请求进行监听,请求到达时候,接收的二进制数据会经过解码后生成HttpMessage,其是对HttpRequestMessage的封装,然后,HttpSelfHostServer会从该HttpMessage提取出HttpRequestMessage,传递给WebAPI消息处理管道的其他处理器依次处理,处理完返回一个HttpResponseMessage对象,把其封装成HttpMessage,接着对其进行编码,通过传输层进行传输,返回给客户端。

  另外,特别注意的是,Web API消息处理管道的最后一个消息处理器还是HttpRoutingDispatcher,其在HttpSelfHostServer创建时候,调用基类HttpServer的构造函数时候指定,而且在HttpRoutingDispatcher路由时候,由于路由数据没在HttpRequestMessage的属性字典中,所以要直接进行路由解析,获得的路由数据也会放在HttpRequestMessage的属性字典中,所以,后续的Controller创建等操作需要的路由数据都是从HttpRequestMessage的属性字典中获取。

  

ASP.NET Web API 框架研究 Self Host模式下的消息处理管道的更多相关文章

  1. ASP.NET Web API 框架研究 Web Host模式下的消息处理管道

    寄宿的作用是开启一个进程为Web API提供一个运行环境以解决持续监听.请求监听和响应回复,即将接收到的请求转换成HttpRequestMessage对象传入管道,并将管道生成并经过处理后的HttpR ...

  2. ASP.NET Web API 框架研究 ASP.NET Web API 路由

    ASP.NET Web API 核心框架是一个独立的.抽象的消息处理管道,ASP.NET Web API有自己独立的路由系统,是消息处理管道的组成部分,其与ASP.NET路由系统有类似的设计,都能找到 ...

  3. ASP.NET Web API 框架研究 Controller实例的销毁

    我们知道项目中创建的Controller,如ProductController都继承自ApiController抽象类,其又实现了接口IDisposable,所以,框架中自动调用Dispose方法来释 ...

  4. ASP.NET Web API 框架研究 Web Host模式路由及将请求转出到消息处理管道

    Web Host 模式下的路由本质上还是通过ASP.NET 路由系统来进行路由的,只是通过继承和组合的方式对ASP.NET路由系统的内部的类进行了一些封装,产生自己专用一套类结构,功能逻辑基本都是一样 ...

  5. ASP.NET Web API 框架研究 核心的消息处理管道

    ASP.NET Web API 的核心框架是一个由一组HttpMessageHandler有序组成的双工消息处理管道:寄宿监听到请求接受后,把消息传入该管道经过所有HttpMessageHandler ...

  6. ASP.NET Web API 框架研究 Action方法介绍

    在根据请求解析出匹配的Controller类型并创建实例后,要在该Controller类型中的众多Action方法中选择与请求匹配的那一个,并执行,然后返回响应. Action方法,其元数据,主要包括 ...

  7. ASP.NET Web API 框架研究 服务容器 ServicesContainer

    ServicesContainer是一个服务的容器,可以理解为—个轻量级的IoC容器,其维护着一个服务接口类型与服务实例之间的映射关系,可以根据服务接口类型获取对应的服务实例.构成ASP.NET We ...

  8. ASP.NET Web API 框架研究 ASP.NET 路由

    ASP.NET Web API 如果采用Web Host方式来寄宿,在请求进入Web API 消息处理管道之前,就会用ASP.NET 自身的路由系统根据注册的路由表,解析出当前请求的HttpContr ...

  9. ASP.NET Web API 框架研究 IoC容器 DependencyResolver

    一.概念 1.IoC(Inversion of Control),控制反转 即将依赖对象的创建和维护交给一个外部容器来负责,而不是应用本身.如,在类型A中需要使用类型B的实例,而B的实例的创建不是由A ...

随机推荐

  1. svn 回滚文件修改

    取消对代码的修改分为两种情况:   第一种情况:改动没有被提交(commit). 这种情况下,使用svn revert就能取消之前的修改. svn revert用法如下: # svn revert [ ...

  2. nodejs TLS 只加密,未授权,进一步完善

    const tls = require('tls'); const fs = require('fs'); const options = { key: fs.readFileSync('my_key ...

  3. BZOJ 1874 取石子游戏 - SG函数

    Description $N$堆石子, $M$种取石子的方式, 最后取石子的人赢, 问先手是否必胜 $A_i <= 1000$,$ B_i <= 10$ Solution 由于数据很小, ...

  4. autohotkey快捷键

    ;已经基本修复了输入带shift的时候跟输入法中英文切换之间的冲突 SetStoreCapslockMode, off SetKeyDelay, ^CapsLock:: #UseHook ;用这个和下 ...

  5. linux 和 主机通信的另类方法

    偶然发现,linux可以从github上直接下载代码.这样就能用windows写好代码,直接给linux来跑了.很方便. 当然是因为我还不会配置网络来让linux和windows通信.弄了一个下午也没 ...

  6. Mac网络命令 老命令重新学

    网络与通信操作 命令名 功能描述 使用举例 telnet 远程登录 telnet hpc.sp.net.edu.cn rlogin 远程登录 rlogin hostname -l username r ...

  7. windows 8 update to windows 8.1

    可以参考以下几个链接: http://blogs.windows.com/windows/b/appbuilder/archive/2013/07/24/windows-8-to-windows-8- ...

  8. 【Web】网页字体图标的使用

    字体图标介绍 网页中图片有很多优点,但也有很多缺点,会增加文件的大小以及增加http请求.这时候就需要用的字体图标(iconfont).字体图标的优点,可以跟图片一样改变透明度.旋转等,本质上是文字, ...

  9. mysql里几个超时配置参数wait_timeout,net_read_timeout等

    以下这些配置项单位都是秒,在mysql命令行中可以使用show global variables like '变量名';可查询配置值. connect_timeout:连接响应超时时间.服务器端在这个 ...

  10. python之函数篇3

    一:函数的定义 1)函数的简单使用,无参函数 def f1(): # 定义函数指定函数名 print("hello") # 指定功能 f1() # 调用函数,才能执行函数体里面的功 ...