• 深入理解WCF系统体系(之二:WCF客户端如何构建?(上))


    前一节(《WCF体系架构(之一:Client与Server信息交互处理流程初略介绍)》)大致介绍了WCF服务消息处理的大致流程,WCF服务的消费者可以是WEB客户端、也可以是其他语言开发的应用程序。
      对于WEB客户端以及其他语言的应用程序,跨平台的性能主要是通过HTTP协议+SOAP消息机制实现。本节主要详细介绍消息在WCF客户端应用程序消息处理流程
    ------------------------------------------------------------------
    -目录: 
    -1、WCF通过客户端代理调用 服务
    -2、实际代理如何映射到服务目标对象上
    -3、WCF客户端框架的核心ClientRuntime建立过程
    -4、ImmutableClientRuntime对象的作用
    -5、客户端操作选择器MethodInfoOperationSelector
    -6、ProxyOperationRuntime的作用
    ------------------------------------------------------------------


    1、WCF如何处理客户端消息调                          


      如果有.Net Remoting开发经验,大家一定还记得在Remoting的客户端,调用服务通过透明代理(TransparentProxy)来对服务进行调用,然后透明代理将对服务的调用转交给实际代理(RealProxy)。在WCF同样如此。那透明代理对应的实际代理又是什么类型的呢。?看看下面的测试例子就知道了。

    var instanceContext = new InstanceContext(new CalculatorCallback());
    using (var channkeFactory = new DuplexChannelFactory<ICalculator>(instanceContext, "calculator"))
    {
        ICalculator proxy = channkeFactory.CreateChannel();
        Console.WriteLine("是否是透明代   理:"+RemotingServices.IsTransparentProxy(proxy));
        Console.WriteLine("透明代理类型:" + proxy.GetType());
    }

     输出结果如下:

    2、实际代理如何映射到服务目标对象上              


    首先看看实际代理对象ServiceChannelProxy字段的定义:

    internal sealed class ServiceChannelProxy : RealProxy, IRemotingTypeInfo
    {
      // Fields
      private const string activityIdSlotName = "E2ETrace.ActivityID";
      private Type interfaceType;
      private MethodDataCache methodDataCache;
      private MbrObject objectWrapper;
      private Type proxiedType;
      private ImmutableClientRuntime proxyRuntime;
      private ServiceChannel serviceChannel;
      /*
      */
      public override IMessage Invoke(IMessage message)
      {
        IMessage message3;
        try
        {
          IMethodCallMessage methodCall = message as IMethodCallMessage;
          if (methodCall == null)
          {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString("SFxExpectedIMethodCallMessage")));
          }
          MethodData methodData = this.GetMethodData(methodCall);
          switch (methodData.MethodType)
          {
            case MethodType.Service:
              return this.InvokeService(methodCall, methodData.Operation);
     
            case MethodType.BeginService:
              return this.InvokeBeginService(methodCall, methodData.Operation);
     
            case MethodType.EndService:
              return this.InvokeEndService(methodCall, methodData.Operation);
     
            case MethodType.Channel:
              return this.InvokeChannel(methodCall);
     
            case MethodType.Object:
              return this.InvokeObject(methodCall);
     
            case MethodType.GetType:
              return this.InvokeGetType(methodCall);
           }
          throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Invalid proxy method type", new object[0])));
        }
        catch (Exception exception)
        {
          if (Fx.IsFatal(exception))
          {
            throw;
          }
          message3 = this.CreateReturnMessage(exception, message as IMethodCallMessage);
        }
        return message3;
    }
     
      private IMethodReturnMessage InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
    {
      object[] objArray;
      object[] ins = operation.MapSyncInputs(methodCall, out objArray);
      object ret = this.serviceChannel.Call(operation.Action, operation.IsOneWay, operation, ins, objArray);
      object[] returnArgs = operation.MapSyncOutputs(methodCall, objArray, ref ret);
      return this.CreateReturnMessage(ret, returnArgs, methodCall);
      }
    }

      先对这几个对象做个介绍:

    1. interfaceType与proxiedType就是服务契约的Type,methodDataCache存放方法信息的容器
    2. objectWrapper:建立代理对象与服务对象之间映射关系的对象
    3. proxyRuntime:是恒定客户端运行时(这个是我自己翻译的,只在此有意义。为了区分它与客户端运行时ClientRuntime的区别而已)。同ClientRuntime一样,它也是WCF客户端体系中很重要的一个对象,它涉及到调用信息的序列化、反序列化、IClientOperationsSelector、IClientMessageInspector、IChannelInitializer等核心对象,稍后会介绍到。
    4. serviceChannel:服务信道。

    其中有个 MbrObject类型的 objectWrapper定义。MbrObject的定义如下:

    private class MbrObject : MarshalByRefObject
    {
      // Fields
      private RealProxy proxy;
      private Type targetType;
     
      // Methods
      internal MbrObject(RealProxy proxy, Type targetType)
      {
        this.proxy = proxy;
        this.targetType = targetType;
      }
     
      public override bool Equals(object obj)
      {
        return object.ReferenceEquals(obj, this.proxy.GetTransparentProxy());
      }
     
      public override int GetHashCode()
      {
        return this.proxy.GetHashCode();
      }
     
      public override string ToString()
      {
        return this.targetType.ToString();
      }
    }

      看看它的构造函数使用的参数可知:通过实际代理对象以及目标代理类型,将实际代理对象映射到了实现契约接口的对象上。

      还有个问题:RealProxy是映射到了最终服务对象上,那是通过什么样的方式或者说是如何进行映射的呢。?
    ServiceChannelProxy对象在WCF体系内部构造ServiceChannelProxy对象时有个构造函数,它建立了代理对象与实际服务对象:this.objectWrapper = new MbrObject(this, proxiedType);这样就建立了代理对象同服务对象之间的映射

      查看代理信息就发现了他们之间的关系,如下图:


    客户端调用服务端方法最终通过ServiceChannelProxy进行调用。以上只列出了同步调用的方法,在ServiceChannelFactory中还有异步调用的方法,详情请参见ServiceChannelFactory类。
    从InvokeService中可以看出,进行调用的时候,使用了serviceChannel.Call进行调用。同样,在异步方法中也是通过ServiceChannel对象的BeginInvoke与EndInvoke进行调用。也就是说最终的调用是通过ServiceChannel完成。

    3、WCF客户端框架的核心ClientRuntime建立过程


      ClientRuntime是与WCF服务端框架中DispatchRuntime对应的客户端框架的核心。那么ClientRuntime是如何建立的。?

      ClientRuntime建立的过程比较复杂。下面通过序号标明ClientRuntime建立的过程。

    3.1、建立Channel                                                       


      无论在WCF的客户端还是服务端,我们通常都会选择一种或者多种通信协议。绑定协议包含许多绑定元素(BindingElementCollection)。以NetTcpBinding来说,它就包含 以下四种绑定元素:
    TransactionFlowBindingElement context;
    BinaryMessageEncodingBindingElement encoding;
    ReliableSessionBindingElement session;
    TcpTransportBindingElement transport;

    每个绑定元素穿件信道工厂,BindingElementCollection创建的是信道工厂堆栈,信道就是由这些ChannelFactory Stack按照顺序依次建立起来的Channel Stack。


    3.2、建立过程ChannelFactory                                       


      先看看以下例子:var channkeFactory = new DuplexChannelFactory<ICalculator>(instanceContext, "calculator");这样就信道工厂就建立。在这个例子中用回调对象对象与EndpointName为参数建立ChannelFactory。

    DuplexChannelFactory有很多构造器,
    public class DuplexChannelFactory<TChannel> : ChannelFactory<TChannel>
    {
      // Methods
      public DuplexChannelFactory(object callbackObject) : base(typeof(TChannel))
      {
        using (ServiceModelActivity activity = DiagnosticUtility.ShouldUseActivity ? ServiceModelActivity.CreateBoundedActivity() : null)
        {
          if (DiagnosticUtility.ShouldUseActivity)
          {
            ServiceModelActivity.Start(activity, SR.GetString("ActivityConstructChannelFactory", new object[] { TraceUtility.CreateSourceString(this) }), ActivityType.Construct);
          }
          if (callbackObject == null)
          {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("callbackObject");
          }
          this.CheckAndAssignCallbackInstance(callbackObject);
          base.InitializeEndpoint((string) null, null);
        }
      }
     
    public DuplexChannelFactory(object callbackObject, string endpointConfigurationName) : this(callbackObject, endpointConfigurationName, (EndpointAddress) null)
    {
    }
     
    public DuplexChannelFactory(object callbackObject, string endpointConfigurationName, EndpointAddress remoteAddress) : base(typeof(TChannel))
    {
      using (ServiceModelActivity activity = DiagnosticUtility.ShouldUseActivity ? ServiceModelActivity.CreateBoundedActivity() : null)
      {
        if (DiagnosticUtility.ShouldUseActivity)
        {
          ServiceModelActivity.Start(activity, SR.GetString("ActivityConstructChannelFactory", new object[] { TraceUtility.CreateSourceString(this) }), ActivityType.Construct);
        }
        if (callbackObject == null)
        {
          throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("callbackObject");
        }
        if (endpointConfigurationName == null)
        {
          throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpointConfigurationName");
        }
        this.CheckAndAssignCallbackInstance(callbackObject);
        base.InitializeEndpoint(endpointConfigurationName, remoteAddress);
      }
     }
    /*
    ......
    */
    }

      

    以上列举了上述例子中使用的构造器。从中可知:在创建ChannelFactory的过程中,通过ChannelFactory<TChannel>的InitializeEndpoint对Endpoint进行了初始化。


    3.3、根据建立的Endpoint创建ServiceChannelFactory              

    从ClientRuntime clientRuntime = DispatcherBuilder.BuildProxyBehavior(serviceEndpoint, out parameters);

    可知:ClientRuntime 由DispatcherBuilder创建。
    注:ServiceChannel由ServiceChannelFactory创建,同ServiceChannelProxy使用。在创建ServiceChannel的过程中对Channel进行初始化。处理函数如下:

    public object CreateChannel(Type channelType, EndpointAddress address, Uri via)
    {
        if (via == null)
        {
          via = this.ClientRuntime.Via;
          if (via == null)
          {
            via = address.Uri;
          }
        }
        ServiceChannel serviceChannel = this.CreateServiceChannel(address, via);
        serviceChannel.Proxy = CreateProxy(channelType, channelType, MessageDirection.Input, serviceChanne);
        serviceChannel.ClientRuntime.GetRuntime().InitializeChannel((IClientChannel) serviceChannel.Proxy);
        OperationContext current = OperationContext.Current;
        if ((current != null) && (current.InstanceContext != null))
        {
          current.InstanceContext.WmiChannels.Add((IChannel) serviceChannel.Proxy);
          serviceChannel.WmiInstanceContext = current.InstanceContext;
        }
        return serviceChannel.Proxy;
    }

    3.4、DispatcherBuilder创建ClientRuntime

    internal class DispatcherBuilder
    {
      internal static ClientRuntime BuildProxyBehavior(ServiceEndpoint serviceEndpoint, out BindingParameterCollection parameters)
      {
        parameters = new BindingParameterCollection();
        SecurityContractInformationEndpointBehavior.ClientInstance.AddBindingParameters(serviceEndpoint, parameters);
        AddBindingParameters(serviceEndpoint, parameters);
        ContractDescription contract = serviceEndpoint.Contract;
        ClientRuntime parent = new ClientRuntime(contract.Name, contract.Namespace);
        parent.ContractClientType = contract.ContractType;
        IdentityVerifier property = serviceEndpoint.Binding.GetProperty<IdentityVerifier>(parameters);
        if (property != null)
        {
          parent.IdentityVerifier = property;
        }
        for (int i = 0; i < contract.Operations.Count; i++)
        {
          OperationDescription operation = contract.Operations[i];
          if (!operation.IsServerInitiated())
          {
            BuildProxyOperation(operation, parent);
          }
          else
          {
            BuildDispatchOperation(operation, parent.CallbackDispatchRuntime, null);
          }
        }
        ApplyClientBehavior(serviceEndpoint, parent);
        return parent;
      }
    /**/
    }

      由Endpoint信息可以获取到ContractDescription,进而获取到Operations等等,从而赋值给ClientRuntime对象,完成ClientRuntime对象的建立。

    以上还有个问题:DispatchRuntime 是与ClientRuntime相对象的WCF服务端分发运行时,同ClientRuntime一样,它是WCF服务端核心对象。在客户端怎么会后服务端的的分发运行时呢。?原因很简单,在WCF数据包模式以及Request-Reply模式下,DispatchRuntime是不需要的,但是在双工模式时,Server端与Client端已经不明确,
    Server与Client互发消息,即是服务端也是客户端。所以不仅在ClientRuntime中存在DispatchRuntime,在DispatchRuntime同样存在ClientRuntime。

    ClientRuntime作为客户端框架的核心,它决定着消息的格式化(IClientMessageFormatter)、客户端操作选择器(IClientOperationSelector)、客户端消息检查器(IClientMessageInspectors)等等。

    4、ImmutableClientRuntime对象的作用                   


      客户端对服务端的操作是通过TransparentProxy到RealProxy,也就是ServiceChannelProxy对象中。上面提到过,客户端调用服务的实际代理ServiceChannelProxy对象有一个名称为proxyRuntime的字段,类型就是ImmutableClientRuntime。
      ImmutableClientRuntime对象依赖于ClientRuntime,这点可以从ImmutableClientRuntime的构造函数中就可以看出。

    internal ImmutableClientRuntime(ClientRuntime behavior)
    {
        this.channelInitializers = EmptyArray<IChannelInitializer>.ToArray(behavior.ChannelInitializers);
        this.interactiveChannelInitializers = EmptyArray<IInteractiveChannelInitializer>.ToArray(behavior.InteractiveChannelInitializers);
        this.messageInspectors = EmptyArray<IClientMessageInspector>.ToArray(behavior.MessageInspectors);
        this.operationSelector = behavior.OperationSelector;
        this.useSynchronizationContext = behavior.UseSynchronizationContext;
        this.validateMustUnderstand = behavior.ValidateMustUnderstand;
        this.unhandled = new ProxyOperationRuntime(behavior.UnhandledClientOperation, this);
        this.addTransactionFlowProperties = behavior.AddTransactionFlowProperties;
        this.operations = new Dictionary<string, ProxyOperationRuntime>();
        for (int i = 0; i < behavior.Operations.Count; i++)
        {
          ClientOperation operation = behavior.Operations[i];
          ProxyOperationRuntime runtime = new ProxyOperationRuntime(operation, this);
          this.operations.Add(operation.Name, runtime);
        }
        this.correlationCount = this.messageInspectors.Length + behavior.MaxParameterInspectors;
    }

    ImmutableClientRuntime在RealProxy中起着至关重要的作用。如下图是RealProxy的信息:

    由上图可知:

    1、operations为Dictionary<string, ProxyOperationRuntime>类型,其中key为契约接口中标识位OperationContractAttribute的方法名,Value为ProxyOperationRuntime。

    2、MessageInspector是实现了IClientMessageInspector接口的Microsoft.VisualStudio.Diagnostics.ServiceModelSink.StubClientEventSink类型。
    3、客户端OperationSelector是MethodInfoOperationSelector类型的,MethodInfoOperationSelector实现了IClientOperationSelector接口。
    4、客户端消息检查器IClientMessageInspectors为Microsoft.VisualStudio.Diagnostics.ServiceModelSink.StubClientEventSink类型。


    5、客户端操作选择器MethodInfoOperationSelector。
    通过工具看看MethodInfoOperationSelector的定义如下:

    internal class MethodInfoOperationSelector : IClientOperationSelector
    {
      // Fields
      private Dictionary<object, string> operationMap = new Dictionary<object, string>();
     
      // Methods
      internal MethodInfoOperationSelector(ContractDescription description, MessageDirection directionThatRequiresClientOpSelection)
      {
        for (int i = 0; i < description.Operations.Count; i++)
        {
          OperationDescription description2 = description.Operations[i];
          if (description2.Messages[0].Direction == directionThatRequiresClientOpSelection)
          {
            if ((description2.SyncMethod != null) && !this.operationMap.ContainsKey(description2.SyncMethod.MethodHandle))
            {
              this.operationMap.Add(description2.SyncMethod.MethodHandle, description2.Name);
            }
            if ((description2.BeginMethod != null) && !this.operationMap.ContainsKey(description2.BeginMethod.MethodHandle))
            {
            this.operationMap.Add(description2.BeginMethod.MethodHandle, description2.Name);
            this.operationMap.Add(description2.EndMethod.MethodHandle, description2.Name);
            }
          }
        }
      }
     
      public string SelectOperation(MethodBase method, object[] parameters)
      {
        if (this.operationMap.ContainsKey(method.MethodHandle))
        {
          return this.operationMap[method.MethodHandle];
        }
        return null;
      }
     
      // Properties
      public bool AreParametersRequiredForSelection
      {
        get
        {
          return false;
        }
      }
    }

      

    operationMap为存放方法的字段,key方法句柄信息,Value为方法名。
    MethodInfoOperationSelector通过SelectOperation根据方法句柄值获取方法名,然后通过方法名,获取ProxyOperationRuntime对象。


    查看OperationSelector的operationMap中Add方法的句柄值如下图所示:


    通过控制台输出契约接口中方法的句柄值如下:


    -6、ProxyOperationRuntime的作用

    了解它的作用,还是从源码开始。

    由上图可以得知:
    1、对返回值进行序列化时,使用的类型是PrimitiveOperationFormatter,它同时实现了客户端序列化接口IClientMessageFormatter与服务端序列化IDispatchMessageFormatter接口
    2、错误契约使用的序列化器是DataContractSerializerFaultFormatter。
    3、对服务调用参数的序列化以及参数检查,对返回消息进行反序列化及参数检查通过ProxyOperationRuntime对象完成。

      对实际代理ServiceChannelProxy对象中的ImmutableClientRuntime类型的字段realProxy以及realProxy的MessageInspector、operations添加监视,查看其信息如下:

    图1:realProxy监视信息

    图2:realProxy的消息检查器MessageInspector监视信息

    图3:realProxy的operations监视信息

    由以上3个图中显示的信息可知:

    1、operations为Dictionary<string, ProxyOperationRuntime>类型,其中key为契约接口中标识位OperationContractAttribute的方法名,Value为ProxyOperationRuntime。

    2、MessageInspector是实现了IClientMessageInspector接口的客户端消息检查器Microsoft.VisualStudio.Diagnostics.ServiceModelSink.StubClientEventSink类型。
    3、客户端OperationSelector是MethodInfoOperationSelector类型的,MethodInfoOperationSelector实现了IClientOperationSelector接口。

    参考:http://www.cnblogs.com/artech/tag/WCF/

       《WCF揭秘》

    WCF
     
    深入理解WCF系统体系(之二:WCF客户端如何构建?(上))
    摘要: 前一节(《WCF体系架构(之一:Client与Server信息交互处理流程初略介绍)》)大致介绍了WCF服务消息处理的大致流程,WCF服务的消费者可以是WEB客户端、也可以是其他语言开发的应用程序。 对于WEB客户端以及其他语言的应用程序,跨平台的性能主要是通过HTTP协议+SOAP消息机制实现。本节主要详细介绍消息在WCF客户端应用程序消息处理流程-------------------------------------------------------------------目录: -1、WCF通过客户端代理调用 服务-2、实际代理如何映射到服务目标对象上-3、WCF客户端框架的核...阅读全文
    posted @ 2012-03-31 14:30 tyb1222 阅读(649) | 评论 (3) 编辑
     
    WCF体系架构(之一:Client与Server信息交互处理流程初略介绍)
    摘要: WCF在设计的时候,就封装了对常用协议如Tcp\HTTP\MSMQ的处理机制。但WCF同时也允许开发者在WCF现有平台上进行扩展,以解决实际问题。 大部分情况下,通过WCF常用的协议,就已经能完成了大部分工作了。在WCF揭秘中,作者在介绍如何扩展WCF时,讲了一些WCF是如何处理行为、信道、传输等方面的工作机制。本节从WCF行为作为切入点,谈谈个人对WCF体系的理解。 在WCF框架设计时,为了简化WCF普通的应用场景,也为了满足一些特殊环境下的应用,WCF的设计者们将WCF进行分成设计。实现方式是将上层 与底层应用区分开。在一些特殊环境下对底层做一些扩展就行了。WCF将一般场景使用的的...阅读全文
    posted @ 2012-03-29 14:49 tyb1222 阅读(796) | 评论 (0) 编辑
     
    SOAP消息机制简介
    摘要: SOAP(Simple Object Access Protocol,简单对象访问协议)作为一种信息交互协议在分布式应用中非常广泛,如WebService。在使用.Net开发WebService时候,只需要在对应的方法上加上WebMethod特性然后就可以通过网络进行SOAP消息的发送。这样在平时使用Webservice时,可能不太关心SOAP消息的结构到底是怎样的。下面大致说说SOAP消息的结构,以及使用工具监听SOAP消息报文。本节目录:1、XSD是什么2、基于SOAP的数据交互系统是XSD的3、SOAPSOAP消息结构4、支持SOAP的协议5、通过SOAPHeader扩展SOAP6、..阅读全文
    posted @ 2012-03-01 14:43 tyb1222 阅读(1228) | 评论 (0) 编辑
     
    REST笔记(四):Atom发布协议------ AtomPub
    摘要: 前一节介绍了一种IETF推荐的一种超媒体格式------Atom,这一节中主要Atom发布协议-------Atom Publish Protocol,简称AtomPub,有时更简洁写作APP。 开篇之前介绍几个重要概念先: 1、媒体类型 描述相关资源表述所使用的类型,如XML、JSON、JPG、MP3等、处理模型以及链接关系值 2、HTTP惯用语 它规范了如何对资源进行操作以及处理HTTP头信息和状态码 3、领域应用协议。 领域应用协议(Domain Application Protocol DAP),它为服务端与客户单的资源的交互定义了一套规范,如资源的媒体类型、链接关系...阅读全文
    posted @ 2011-12-21 16:07 tyb1222 阅读(786) | 评论 (1) 编辑
     
    Jquery+JSON消费REST WCF4.0 服务(带源码)
    摘要: 作为一种以HTTP协议为基础的WCF 服务,只要客户端能模拟进行HTTP请求,都能成为服务的消费者。之前写过《对Jquery+JSON+WebService的一点认识》,觉得在REST是基于HTTP协议的,AJAX的操作也应该一样。但是事实上还是有些差别的。由于网上资源聊聊无几,因此记录下自己的个人体会。希望对你有些帮助! 本篇主要讲述的类容为在ASP.NET中,如何通过AJAX来消费REST服务。 使用JQUERY框架模拟AJAX请求时,操作类型主要有GET、POST两种。本节也以这两种常用的方式来进行介绍。(type (String) : (默认: "GET") 请求方阅读全文
    posted @ 2011-11-25 19:39 tyb1222 阅读(2120) | 评论 (13) 编辑
     
    在REST WCF中使用HTTP Header进行数据交互
    摘要: 我们知道,在HTTP协议的报文头Header中存放着许多信息。如果你读过老A的《通过添加HTTP Header实现上下文数据在WCF的自动传递》,那你一定知道如何通过底层的扩展来实现如何在REST WCF中使用HTTP Header来进行数据交互。这对于大家更多的了解WCF的底层机制有很大的帮助作用。 窃以为:在实际的REST WC应用中,想通过Header头来实现数据交互不用那么麻烦。MicroSoft在它所提供的库中就已经为我们封装好了一些接口,可以很容易的让我们实现这一功能。 HTTP Header报文头可以在Server与Client之间传递很多数据。我们可以获取这些数据然后进...阅读全文
    posted @ 2011-11-23 18:42 tyb1222 阅读(966) | 评论 (7) 编辑
     
    REST WCF 使用Stream进行Server与Client交互
    摘要: 上节介绍了REST WCF 4.0相比3.5支持更多的交互格式,本篇就说说在Server与Client间通过最原始的流的格式进行通讯。开篇之前,介绍REST WCF 的一个特性:DescriptionAttribute。对这个特性相信都很熟悉,它的作用如同在WebService中通过它来标注出某个接口的描述信息,在REST WCF中同样如此。将它标注在REST WCF 接口中后,在help页面中将会显示接口的描述信息。 如以往,本篇将通过Demo的形式介绍如何在REST WCF中使用Stream。Demo的功能有以下几点: 1、通过Stream的形式获取服务端的图片资源,并保存到本地 ...阅读全文
    posted @ 2011-11-18 19:08 tyb1222 阅读(1127) | 评论 (5) 编辑
     
    REST WCF 4.0 新特性简介
    摘要: 前面几节介绍了REST WCF 3.5的一些基本特性以及使用方式,在WCF4.0的时代,也做了对REST的支持。相比3.5时代,4.0改进体现有如下几点:增加对路由的支持对缓存的支持。帮助(help)页面的改进。消息错误处理消息格式的多样性如(XML\JSON\ATOM\TEXT\BINARY)简化操作。 本节讲述的重点为如何使用路由注册REST服务、缓存以及help页面 1、使用路由注册服务。 WCF4.0中新增的路由服务可以帮助直接注册服务,而不再需要SVC的文件。 需要注意的是,使用路由注册服务时必须启动ASP.NET的兼容模式。即设置aspNetCompatibilityE...阅读全文
    posted @ 2011-11-16 17:35 tyb1222 阅读(1206) | 评论 (2) 编辑
     
    .Net Remoting与WCF实现Server与Client通讯比较
    摘要: .Net Remoting是微软早前推出的一项分布式通讯技术框架,在.Net架构的程序中有着比较广泛的应用。在WCF中,已经集成了Remoting的技术。不过,他们有着很多相同的概念,如:信道(Channel)、代理(Proxy)、寄宿(host)等。在如今仍有一些分布式系统应用中运行着由Remoting技术构建的系统。本文将描述在服务端与客户端的交互中,他们各自的实现方式。 1、Remoting的实现。 在Remoting中,远程对象是一个重要的概念。服务端通过将它注册到制定的信道中,客户端服务...阅读全文
    posted @ 2011-11-12 20:26 tyb1222 阅读(1211) | 评论 (0) 编辑
     
    对REST架构 风格下WCF的一点补充
    摘要: 这几天思考REST 架构下POST复杂数据类型的问题查了写资料,以及通过与WCF 大牛------Frank Xulei进行了一番交流对REST有了一些进一步的认识。本篇作为:1、REST与SOA两种架构下WCF的异同比较 2、通过HTTP协议标准动作使用REST WCF 服务这两篇的一个补充。 起因是这样的:在SOA架构下,一般都是通过定义服务契约的方式最终通过WSDL将元数据对外发布,以供调用者使用。也就是说在SOA中,通过服务契约定义向外公布服务对外提供的操作。如果先学习SOA,然后接触REST,可能会在使用REST的时候会沿用SOA下的一些习惯。我在进行REST架构下的WCF学...阅读全文
    posted @ 2011-11-09 20:47 tyb1222 阅读(970) | 评论 (0) 编辑
     
    通过Fiddler测试你的 REST WCF服务
    摘要: Fiddler是一款强大的软件,在实际的开发中它能帮助我们跟踪HTTP请求,记录发送请求和获取到请求结果的数据。使用VS2008的时候,一直是用IE6浏览调试,使用Fiddler也正常。但本人一直习惯用FireFox,可怜用它访问的时Fiddler却不能帮助记录下数据(FireFox版本:4.0)。还以为Fiddle只能在IE下使用,试了试chrome,发现也可以用。言归正卷,本篇针对上篇中的REST服务(具体例子以及带代码采用上节中介绍的:通过HTTP协议标准动作使用REST WCF 服务)使用Fiddler简要做一个介绍。首先大致说说Fiddler的界面,如图: ...阅读全文
    posted @ 2011-11-07 18:23 tyb1222 阅读(1484) | 评论 (3) 编辑
     
    通过HTTP协议标准动作消费REST WCF 服务
    摘要: 前几节介绍了REST WCF 服务的一些基本的特点,本节说明一下,如何基于HTTP的标准动作来使用REST WCF 服务。由于RESTful服务的架构风格基于HTTP协议,并且其设计原则中明确指出:通过通用的连接器接口来使用资源。对于REST架构风格的服务,主要通过它8个动作中的4个来使用资源,即:GET,POST,PUT,DELETE。 在RESTful 服务中,GET,POST,PUT,DELETE的标准操作如下: GET:获取资源 POST:修改资源 PUT:创建资源 DELETE:删除资源本节涉及的要点如下:1、如何定义接口规范,使客户端通过能通过HTTP协议的标准动作来...阅读全文
    posted @ 2011-11-02 18:25 tyb1222 阅读(1247) | 评论 (3) 编辑
     
    REST下的WCF的寄宿方式
    摘要: 如同SOA下的WCF,REST架构下的WCF也有多种多样的寄宿方式,如IIS寄宿,自寄宿等等,即使它只有一种协议。由于REST基于HTTP协议的特点,所以这种架构下的WCF寄宿时,需要有Web服务器的支持。那么很显然,微软肯定会使用自己的Web服务器IIS了。本节目录:1、IIS寄宿2、控制台程序寄宿(暂且将它称为自寄宿)当然,REST WCF还有其他的寄宿方式,我这里只挑出典型的两种给大家介绍。有兴趣的朋友不妨试试其他的寄宿方式。本节中所使用的实例还是上节所使用的例子。Demo结构图如下:结构说明:Client为服务消费者,Contracts定义服务契约、数据契约,Services定义服..阅读全文
    posted @ 2011-10-28 15:50 tyb1222 阅读(988) | 评论 (6) 编辑
     
    REST与SOA两种架构下WCF的异同比较(含源码)
    摘要: REST(Representational State Transfer)与SOA(Service-Oriented Architecture)作为当今软件架构中主流的两种架构思想在当前开发过程中已经越来越流行。作为微软.NET平台下的下一代通讯技术,WCF也很好的体现了对他们的支持。那么他们到底有哪些差别又有哪些相同之处呢。?本篇将针对这个问题谈谈自己的认识,并通过Demo演示程序。本篇设计的内容如下: 1、REST的特性 2、SOA的特征 3、REST与SOA的共同点 4、REST与SOA的不同点 5、Demo程序说明*REST的特性。首先给出一张图:它基于HTTP协议,是一...阅读全文
    posted @ 2011-10-27 17:19 tyb1222 阅读(1407) | 评论 (10) 编辑
     
    REST 架构风格下的WCF特性简介
    摘要: REST(Representational State Transfer)作为一种优秀的架构风格,自诞生以来越来越受广大开发者的青睐。对没有接触过REST的开发人员,可以参阅本人的上一篇博客:对REST架构的理解及Jquery+JSON+RESTful WCF。由于REST推崇的简易型,以及基于HTTP协议的特点,它又有一些什么样的特性呢。?本问将围绕这个主题分两部分展开,并结合Demo程序加以介绍。第一部分介绍涉及到的知识点,第二部分介绍Demo。 主要涉及到的知识点如下: 1、绑定协议与行为(webHttpBinding 与webHttpBehavior) 2、Action的定义...阅读全文
    posted @ 2011-10-26 11:21 tyb1222 阅读(1604) | 评论 (4) 编辑
     
    对REST架构的理解及Jquery+JSON+RESTful WCF (附源码)
    摘要: 最近看了一些REST架构风格的介绍,谈谈自己对REST的理解总结一下自己的认识。本文只最为个人阶段性的成果,供对REST开发有兴趣的童鞋参考。若有理解有误的地方恳请大侠指教。 REST看了好多天了,自己也写了一些DEMO程序加深了对他的理解。晚上突然发现还有个微软之前还发布过一个插件名称(WCF REST Starter Kit Preview 2.msi,下载地址:http://aspnet.codeplex.com/releases/view/24644),供给大家使用。供作为个人第一篇介绍REST风格的WCF文章,本文就从这个插件的最基本的使用说起。 本文分为两个部分: 1、R...阅读全文
    posted @ 2011-10-24 02:50 tyb1222 阅读(2475) | 评论 (9) 编辑


  • 相关阅读:
    2020年9月12日 线程的安全问题:同步方法;
    2020年9月12日 线程的安全问题:线程使用共享数据 产生的安全问题
    2020年9月11日 编写龟兔赛跑的多线程程序
    2020年9月9日 为什么要有包装类、包装类有哪些、装箱与拆箱、包装类的API、包装类对象的缓存问题
    2020年9月4日 try catch finally遇见return的时候返回值是啥?(面试题)
    2020年9月4日 异常
    2020年9月4日 异常处理
    2020年9月3日 内部类总结
    2020年9月3日 静态导入
    2020年9月3日 自定义注解和元注解
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2428208.html
Copyright © 2020-2023  润新知