我的WCF之旅(1):创建一个简单的WCF程序

[原创]我的WCF之旅(1):创建一个简单的WCF程序

 

写在前面

在Microsoft提出.NET战略以来, 先后推出了一系列产品和技术, 这些产品和技术为我们在.NET平台下建立企业级的分布式应用提供了很大的 便利。这些技术和产品包括:.NET  Remoting,XML WebSerivce,WSE(2.0,3.0),Enterprise Service, MSMQ ......

我们知道,和一个相对独立的应用不同,我们开发一个分布式应用, 尤其是开发一个企业级的分布式应用, 我们需要考虑较多的东西。比如我们要考虑数据在不同的应用之间传递时采取什么样的机制, 这种数据传递是否是安全的,可靠的;如何在分布式的环境下进行异常处理;如何把分别在 不同应用中执行的操作纳入同一个事务……

对于我们上面提到的这些 问题, 这些都是开发分布式应用考虑的典型的问题。值得庆幸的是,Microsoft开发的分布式的产品能够部分的解决这些问题。.NET Remoting 为我们在.NET平台下提供了非常好的解决方案(我个人认为,.NET Remoting是.NET平台下最为成熟的分布式技术。比如相较于另一个使用更为广泛的技术XML Web Service,它具有一些自己独特的特性:可以使用不同的传输层协议进行通信——Http & TCP;可以使用不同的消息编码方式——Bianry & Text (XML);可以寄宿到IIS和任何一种托管的应用下 ——Console Application 、WinForm Application、 Windows Service……;Server端可以通过双向通信回调(Callback)客户端的操作;……)XML Web Service为使我们实现跨平台的系统能够集成显得如此简单。随着技术的不断发展,相关的技术规范(WS-* Specification)不断完善, XML Web Service现在已经成为使用最为广泛的分布式技术了。XML Web Service能够得到如此广泛的推广,这得得益于Microsoft先后两次推出的Web Service Enhancement (WSE 2.0 、WSE 3.0)。如果没有WSE, 单纯的asmx下的如此的担保和不可靠。WSE为Web Service解决了几大难题:Security、Reliable Messaging、transaction Handling以及大数据的有效传输。 MSMQ作为一种简单而有效的机制为不同应用之间数据的传递提供了保障。

其实,通过合理利用上面这些分布式的技术完全可以为我们建立的一套适合不同层次需要的分布式构架。但这里面仍然存在一些问题,那就是上面这些技术和产品只能解决某一方面的问题; 比如.NET Remoting虽然在.NET平台下是一个很好的依靠, 但是考虑到他不能提供不同平台之间的互操作性。另外,这些技术适合用了完全不同的编程方式,使得我们很难从容地从其中一种转移到另一种上来。基于这些原因, 我们需要一套全新的技术整合以上都这些技术, 于是我们有了今天的WCF——Windows Communication Foundation。WCF建立一套框架,是我们通过一致的编程模式,使用不同的技术构建我们的分布式应用。 

虽然很早开始接触WCF,但所学的总是零零碎碎。现在开始系统地研究WCF,希望与大家一同分享我的一些所得, 同时希望能通过这样的一个机会与大家一些探讨WCF,不对的地方希望大家指正。

一开始我们先建立一个简单程序看WCF如何工作:

1 建立整个应用的简单构架

整个构架如图所示,这个Solution由5个Project组成:Artech.WCFService.Contract;  Artech.WCFService.Service;Artech.WCFService.Hosting;Artech.WCFService.Client;http://localhost/WCFService

  • Artech.WCFService.Contract: Class Library Project,用来保存Contract(Service Contact、Message Contract、Data Contract), 之所以把Contract独立出来的原因是考虑到他同时被Server端——Service本身和Service Hosting和Client端使用。(现在很多的参考书,包括MSDN都使用ServiceModel Metadata Utility Tool (Svcutil.exe)这样的一个工具来访问Service的Metadata Endpoint来生成我们的客户段代码,这些代码就包括Service Contract(一般是一个Interface),实现了这个Contract的Proxy Class(一个集成自System.ServiceModel.CientBase的一个Class)和相应的Configuration。 这个工具确实给我提供了很大的方便。但我不推荐使用这样的方法(我天生不倾向对于这些代码生成器),因为我觉得, 在Contract可得的情况下-比如Service和Client都是自己开发,让Service和Client实现的Contract是同一个Contract能够保证一致性。这个Project引用System.ServiceModel DLL。
  •   Artech.WCFService.Service:Class Library Project,Service的业务逻辑, 这个Project引用Artech.WCFService.Contract Project和System.ServiceModel DLL。
  •   Artech.WCFService.Hosting:Console Application, 用于以Self-Hosting的方式Host Service。这个Project引用Artech.WCFService.Contract和Artech. Project WCFService.Service。Project和System.ServiceModel DLL。
  •   Artech.WCFService.Client:Console Application, 用以模拟现实中的调用Service的Clinet。这个Project引用Artech.WCFService.Contract Project 和System.ServiceModel DLL。
  •   http://localhost/WCFService: Web Site Project, 用于模拟如何把Service Host到IIS中。这个Project引用Artech.WCFService.Contract、Artech.WCFService.Service和System.ServiceModel DLL。

 

2 创建Service Contract

在这个例子中我们建立一个简单的案例,做一个计算器, 假设我们只要求他做简单的加法运算就可以了。在Artech.WCFService.Contract添加一个interface,名称叫做ICalculator。

 

using  System.Collections.Generic;
using  System.Text;
using  System.ServiceModel;

namespace  Artech.WCFService.Contract
{
    [ServiceContract]
    
public   interface  ICalculator
    {
        [OperationContract]
        
double  Add( double  x,  double  y);
    }
}

使一个Interface成为Service Contract的方法很简单,就是把ServiceContractAttribute应用到这个interface上,并在代表单个Operation的方法上应用OperationContractAttribute。这个使用Custom Attribute的编程模式被称为声明式的编程(Declarative)方式, 他在.NET Framework 1.1以前用到的地方还不是太多,在.NET Framework 2.0, 尤其是NET Framework 3.0中,这种方式已经变得随处可见了。

我们可以把Contract定义成一个Interface,也可以把它定义到一个Class中——这个Class中既包涵Service本身又作为一个Contract而存在。但我推荐使用第一种方法——Serive和Contract相分离。

在WCF中,Contract的功能实际上就定义一个Service包含哪些可用的Operation, 以及的每个Opertaion的方法签名。从消息交换(Message Exchange)的角度讲,Contract定义了调用相应的Serive采取的消息交换的模式(Message Exchange Pattern - MEP),我们经常使用的MEP包括三种:Oneway, Request/Response,和Duplex。因为调用Service的过程实际就是消息交换的过程, 以常见的Request/Response为例。Client调用某个方面远程访问Service,所有的输入参数被封装到Request Soap Message并被发送到Service端, Service端监听到这个Soap Request,创建相应的Service Object并调用相关的操作,最后将Result(这可以是Return Value,Reference Parameter和Output Parameter)封装成Soap Message发送回Client端。这里需要注意,如果采用的是Request/Response的模式,即使相应的操作没有Return Value,Reference Parameter和Output Parameter(它被标记为void),Service仍然会返回一个空的Soap Message给Client端。

3 创建Service

前面我们已经创建了我的Artech.WCFService.Contract。其实我们从Contract这个单词上讲, 它就是一种契约,一种承诺。 他表明在上面签了字你就的履行Contract上义务。Service就是这样一个需要履行Contract义务的人。在这个例子中, Contract以Interface的方式定义的一些Operation。作为Service, 在Contract上签字的方式就是实现这样的一个Interface。 下面的Service得到code, 很简单。

using  System;

using  System.Collections.Generic;

using  System.Text;

using  System.ServiceModel;

using  Artech.WCFService.Contract;

 

namespace  Artech.WCFService.Service

{

    
public   class  CalculatorService:ICalculator

    {

        
#region  ICalculator Members

 

        
public   double  Add( double  x,  double  y)

        {

            
return  x  +  y;

        }

 

        
#endregion

    }

}


4.Hosting Service

就像Remoting一样,我们继承自System.MarshalByRefObject 的对象必须Host到某一个运行的进程中, 他才开始监听来自Client端的请求,当Client才能通过Proxy远程的调用,Remoting Infrastructure监听到来自Client端的请求,他会激活相应的remote Object(我们只考虑Server Activate Object——SAO)。实际上对于WCF Service也需要一个Host环境才有其发挥作用的舞台。就像Remoting一样,你可以使用任何一种Managed Application——Console Application、WinForm Application、ASP.NET Application——作为它的Host环境。 你甚至可以用它Host到Windows Service中和IIS中(后面我将会讲到如何做)。

我们知道WCF中,Client端和Service端是通过Endpoint来通信的,Endpoint有包含3个部分,经典地称为ABC.

A代表Address,它包含一个URI,它指明Service存在于网络的某个地方,也就是说它为Client断指明在什么地方去找到这个Service。很多人认识Address仅仅只是一个具有Identity的URI,实际上不然, Address不止于此, 它还包含一些Header,这些信息在某些情况下对于如何寻址有很大的意义(比如在client的最终Service之间还有一些Intermediary节点的情况下)。 在.NET中, Address用System.ServiceModel.EndpointAddress 来表示。

B代表Binding,Binding封装了所有Client和Service段消息交换的通信细节。比如他定义了通信应该采用的Transport-比如我们是因该采用Http, TCP,Named Pipe或者是MSMQ;通信的内容应该采取怎样的编码——比如是Text/XML,Binary还是MTOM。以上这些都得一个Binding所必须定义的内容, 此外,Binding 还可以定义一些其他的有关通信的内容, 比如Security,Reliable Messaging, Session, Transaction等等。正因为Binding对于通信的重要性,只有Service端的Binding和Client的Binding相互匹配的时候,他们之间在可以相互通信。如何使Client Binding 匹配Service Binding呢?最简单也是最直接的方法就是使用相同的Binding。WCF为我们定义了一系列的System Defined Binding,这些Binding在Transport,Interoperability,Security,Session Support,以及Transaction Support方面各有侧重。基本上WCF为我们定义的这些Binding 已经够我们使用的了,如果,实在满足不了要求, 你还可以建立自己的Custom Binding。

C 代表Contract这在上面已经提及,这里不再累赘。

Host的本质就是把一个Service 置于一个运行中的进程中,并以Endpoint的形式暴露出来,并开始监听来自Client端的请求。这里值得注意的是,同一个Service可以注册若干不同的Endpoint,这样不同的Client就可以以不同的方式来访问同一个Service.比如,同一个Intranet的Client可以以TCP的方式访问Service,另一个存在已Internet中的Client则只能以Http的方式访问。

 

using  System;

using  System.Collections.Generic;

using  System.Text;

using  System.ServiceModel;

using  Artech.WCFService.Contract;

using  Artech.WCFService.Service;

using  System.ServiceModel.Description;

 

namespace  Artech.WCFService.Hosting

{

    
class  Program

    {

        
static   void  Main( string [] args)

        {

            HostingServiceViaCode();

        }

 

        

        
static   void  HostingServiceViaCode()

        { 

            
// Specify the base Address

            Uri baseUri 
=   new  Uri( " http://localhost:8080/calculatorService " );

            
// create a new ServiceHost object and specify the corresponding Service and base Address

            
// It is recommended to apply the using pattern to make sure the sevice host can be closed properly. 

            
using  (ServiceHost calculatorServiceHost  =   new  ServiceHost( typeof (CalculatorService), baseUri))

            {

                
// Create a Binding for Endpoint.

                BasicHttpBinding Binding 
=   new  BasicHttpBinding();

                
// Create a Service Endpoint by specify the Address(it is absolute or relative path based on the base Address, the empty string indicates the Address equals base Address),

                
// Binding(the basicHttpBinding created) and Contrace(it is now the type info of the contract interface)

                calculatorServiceHost.AddServiceEndpoint(
typeof (ICalculator), Binding,  string .Empty);

 

                
// Such a segment of code snip shows how to make the metadata exposed to the outer world by setting the Service metadata behavior

                
// Find the Service metadata behavior if exists, otherwize return null.

                ServiceMetadataBehavior behavior 
=  calculatorServiceHost.Description.Behaviors.Find < ServiceMetadataBehavior > ();

 

                
// If the Service metadata behavior has not to added to the Service. we will create a new one and evaluate the HttpGetEnabled&HttpGetUrl to make outer world can retrieve to metadata.

                
if  (behavior  ==   null )

                {

                    behavior 
=   new  ServiceMetadataBehavior();

                    behavior.HttpGetEnabled 
=   true ;

                    
// HttpGetUrl is absolute or relative based on base Address

                    behavior.HttpGetUrl 
=  baseUri;

                    
// We must add the new behavior created to the behavior collection, otherwize it will never take effect.

                    calculatorServiceHost.Description.Behaviors.Add(behavior);

                }

                
// if the metadata behavior exists in the behavior collection, we just need to evaluate the HttpGetEnabled&HttpGetUrl

                
else

                {

                    behavior.HttpGetEnabled 
=   true ;

                    behavior.HttpGetUrl 
=  baseUri;

                }

 

                
// Add the opened event handler to make a friendly message displayed after opening the Service host indicating the Service begin to listen to request from Clients.

                calculatorServiceHost.Opened 
+=   delegate  { Console.WriteLine( " Calculator Service begin to listen via the Address:{0} " , calculatorServiceHost.BaseAddresses[ 0 ].ToString()); };

                
// Open the Service host make it begin to listen to the Clients.

                calculatorServiceHost.Open();

 

                Console.Read();

            }

        }

    }

}

 

 

我们现在可以单独运行Hosting Projet,以下是运行后的截图。


当Hosting启动之后,由于我们为它开启了Http Enabled,Hosting为专门创建一个Metadata Endpoint,通过访问这个Endpoint,我们可获取Service相关的Metadata。像ServiceModel Metadata Utility Tool (Svcutil.exe) 这得工具就是通过获取Metadata来帮我们生成相应的客户端代码和配置文件。当Hosting被启动之后,我们可以在IE中输入Metadata Endpoint的Address来测试Service的可访问性。如下图。


以上我们完全以代码的方式Host一个已经创建的Service。在这个例子中,Endpoint的所有信息都在代码中指定。实际上真正的项目开发之中,我们基本上不采用这样的方法。这是因为,Service的Addresss以及Binding 信息在开发阶段和部署阶段往往是不一样的。所以我们通常的做法是把这些信息放在Config文件中,这样我们可以根据实际的需求改变存储于Config文件中的信息,比如我们把Service移植上另外的位置,我们只要改变Endpoint的Address配置信息就可以了; 再比如,我们把原来存在Intranet的Service放到Internet上,原来可能基于TCP的Binding必须改成基于Http的Binding,在这种情况下,我们依然可修改配置文件就可以了,这样的改动通常是很小的,并且修改了配置文件之后我们不需要对现有的代码进行重编译和重部署,它们可以其实生效。下面我们来看看如何创建基于Configuration的Hosting。

首先,在Artech.WCFService.Hosting中创建App.config,并编写如下结构的配置信息。

<? xml version="1.0" encoding="utf-8"  ?>

< configuration >

< system .ServiceModel >

    
< Services >

      

 

      
< Service  name ="Artech.WCFService.Service.CalculatorService"  behaviorConfiguration =" calculatorBehavior" >

        
< host >

          
< baseAddresses >

            
< add  baseAddress ="http://localhost:8888/GeneralCalculator" />

          
</ baseAddresses >

        
</ host >

        
< Endpoint  Address =""  Binding  ="basicHttpBinding"  contract ="Artech.WCFService.Contract.ICalculator" ></ Endpoint >

      
</ Service >

    
</ Services >

 

    
< behaviors >

      
< ServiceBehaviors >

        
< behavior  name ="calculatorBehavior" >

          
< ServiceMetadata  httpGetEnabled ="true"  httpGetUrl ="" />

      
</ ServiceBehaviors >

    
</ behaviors >

    

 
</ system.ServiceModel >

</ configuration >


然后我们相应地改变我们的Hosting代码,现在由于我们的Endpoint的信息都放在我们的配置文件中,所以我们可以较大的简化我们的Hosting 代码。

using  System;

using  System.Collections.Generic;

using  System.Text;

using  System.ServiceModel;

using  Artech.WCFService.Contract;

using  Artech.WCFService.Service;

using  System.ServiceModel.Description;

 

namespace  Artech.WCFService.Hosting

{

    
class  Program

    {

        
static   void  Main( string [] args)

        {

            
using  (ServiceHost calculatorServiceHost  =   new  ServiceHost( typeof (CalculatorService)))

            {

                calculatorServiceHost.Opened 
+=   delegate  { Console.WriteLine( " Calculator Service begin to listen via the Address:{0} " , calculatorServiceHost.BaseAddresses[ 0 ].ToString()); };

                calculatorServiceHost.Open();

                Console.Read();

            }

        }

    }

}


当calculatorServiceHost.Open();被调用之后,系统会查看calculatorServiceHost对应的Service的类型,结果发现它的类型是Artech.WCFService.Service. CalculatorService(在ServiceHost被创建时最为第一个传入参数);然后会在config文件中Services部分中找name属性和这个Service type相匹配,找到之后,把它host进来,然后添加它在配置文件中定义的所有的Endpoint,并设置在配置文件中定义的所有Binding 以及 Behavior。

现在我们运行Hosting,将会得到同上面一样的结果。同样,在IE中输入Metadata Endpoint的Address,也会看到上解图一样的显示。

5.创建Client

到现在为止,Service端的工作已经完成,当你启动Hosting的时候,一个可用的Service就已经存在了。现在所做的事情是如何创建我们的客户段程序去使用这个Service。几乎所有的WCF的书,其中包括MSDN都是叫你如何使用Service Utility这样的一个工具来帮你生成客户端代码和配置信息。为了让我们能够清晰的Client的整体内容, 我们现在选择手工的方式来编写这样的部分代码。

几乎所有分布式的调用都有这样的一个概念,调用的具体实现被封装在Server端,Client不可能也不需要了解这个具体实现,它所关心的就是我如何去调用,也就是说Cient需要的不是Service的实现,而是一个interface。WCF也是一样,Client不需要了解Service的具体实现,它只需要获得Service 的Contract,已经如何与Service通信就足够了。说到Contract和通信,我们很自然地会想到Endpoint,不错,Endpoint恰恰给我们提供这两个方面的内容。所以到现在我们可以这样说,这样在Client建立和Serivce端相匹配的Endpoint,Client就可以调用它所希望的Service。前面提到Endpoint包括三个部分, Address, Binding,Contract那我们现在来看看Client如何获得这3要素的信息。

在System。Service。Model 命名空间里,定义了一个类abstract class ClientBase<TChannel>,给我们调用Service提供极大的便利。我们只要是我们的Client继承这样一个类,并为它指定Endpoint的三要素就一切OK了,下面我们来看看我们可以以那些方式来指定这些内容

1. Conract:我们看到了ClientBase是一个Generic的类,我们在创建一个继承自这个类的时候必须给它指定特定的TChannel.我们可以把Contract对应的类型作为Client的generic类型。

2. Binding和Address:和Service端的Endpoint一样,我们可以把相关的信息放在我们的Client端代码里面,也可以放在Client的Config里面。那个这些数据如何应用要我们创建的派生自ClientBase的类的对象上呢。其实很简单,ClientBase给我们定义了若干重载的构造函数,我们只要定义我们相应的构造函数应简单地调用基类的构造函数。下面列出了ClientBase定义的全部的构造函数

protected ClientBase():这个构造函数没有任何的参数,它用于Endpoint的信息全部存放于Config

protected ClientBase(InstanceContext callbackInstance):指定一个Callback instance用于Service回调Client代码,这用Deplex Communication。

protected ClientBase(string EndpointConfigurationName):指定一个ID,它标识configuration 文件中定义的某一个Endpoint。这个方法在使用不同的Endpoint调用同一个Service的情况下用到的比较多。

  • ClientBase(Binding Binding, EndpointAddress remoteAddress);显示的指定Binding 和Address
  • ClientBase(InstanceContext callbackInstance, string EndpointConfigurationName)
  • ClientBase(string EndpointConfigurationName, EndpointAddress remoteAddress)
  • ClientBase(string EndpointConfigurationName, string remoteAddress)
    ClientBase(InstanceContext callbackInstance, Binding Binding, EndpointAddress remoteAddress)
  • ClientBase(InstanceContext callbackInstance, string EndpointConfigurationName, EndpointAddress remoteAddress)
  • ClientBase(InstanceContext callbackInstance, string EndpointConfigurationName, string remoteAddress)

介绍完ClientBase后, 我们来创建我们自己的CalculatorClient。下面的相应的Code

using  System;

using  System.Collections.Generic;

using  System.Text;

using  System.ServiceModel;

using  System.ServiceModel.Channels;

using  Artech.WCFService.Contract;

 

namespace  Artech.WCFService.Client

{

    
class  CalculatorClient:ClientBase < ICalculator > ,ICalculator

 

    {

        
internal  CalculatorClient()

            : 
base ()

        { }

 

        
#region  ICalculator Members

 

        
public   double  Add( double  x,  double  y)

        {

            
return   this .Channel.Add(x, y);

        }

 

        
#endregion

    }

}


上面的例子中我们仅仅定义了一个无参的构造函数,因为我们会把所有的Endpoint信息放在Config文件里面:

<? xml version="1.0" encoding="utf-8"  ?>

< configuration >

 
< system .ServiceModel >

    
< Client >

            
< Endpoint  Address ="http://localhost:8080/WCFService/CalculatorService "  Binding ="basicHttpBinding"  contract ="Artech.WCFService.Contract.ICalculator"   />

          
</ Client >     

 
</ system.ServiceModel >

</ configuration >

然后我们再Client Project中的Program class里面通过这样的方式调用CalculatorService;

using  System;

using  System.Collections.Generic;

using  System.Text;

using  System.ServiceModel;

using  System.ServiceModel.Channels;

using  Artech.WCFService.Contract;

 

namespace  Artech.WCFService.Client

{

    
class  Program

    {

        
static   void  Main( string [] args)

        {

            
try

            {

                  
using  (CalculatorClient caluclator  =   new  CalculatorClient())

                    {

                                Console.WriteLine(
" Begin to invocate the calculator Service " );

                                Console.WriteLine(
" x + y = {2} where x = {0} and y = {1} " 1 2 , caluclator.Add( 1 2 ));

 

                                Console.Read();

                      }

                }

            }

 

            
catch  (Exception ex)

            {

                Console.WriteLine(
" StackTrace:{0} " , ex.StackTrace);

                Console.WriteLine(
" Message:{0} " , ex.Message);

                Console.Read();

            }            

        }        

    }

}

WCF相关内容:
[原创]我的WCF之旅(1):创建一个简单的WCF程序
[原创]我的WCF之旅(2):Endpoint Overview
[原创]我的WCF之旅(3):在WCF中实现双向通信(Bi-directional Communication)
[原创]我的WCF之旅(4):WCF中的序列化(Serialization)- Part I
[原创]我的WCF之旅(4):WCF中的序列化(Serialization)- Part II
[原创]我的WCF之旅(5):Service Contract中的重载(Overloading)
[原创]我的WCF之旅(6):在Winform Application中调用Duplex Service出现TimeoutException的原因和解决方案
[原创]我的WCF之旅(7):面向服务架构(SOA)和面向对象编程(OOP)的结合——如何实现Service Contract的继承
[原创]我的WCF之旅(8):WCF中的Session和Instancing Management
[原创]我的WCF之旅(9):如何在WCF中使用tcpTrace来进行Soap Trace
[原创]我的WCF之旅(10): 如何在WCF进行Exception Handling
[原创]我的WCF之旅(11):再谈WCF的双向通讯-基于Http的双向通讯 V.S. 基于TCP的双向通讯

[原创]我的WCF之旅(12):使用MSMQ进行Reliable Messaging
[原创]我的WCF之旅(13):创建基于MSMQ的Responsive Service

posted on 2007-02-26 11:13 Artech 阅读(29667) 评论(166)  编辑 收藏

评论

#1楼  2007-02-26 11:19 Leepy      

收藏,有时间看看!   回复  引用  查看    

#2楼  2007-02-26 12:10 IT      

能把源代码发不上来,学习学习吗??   回复  引用  查看    

#3楼  2007-02-26 12:40 webabcd      

支持   回复  引用  查看    

#4楼  2007-02-26 13:01 JesseZhao      

嘿嘿 ,支持以下   回复  引用  查看    

#5楼  2007-02-26 16:31 钱彦云      

收藏,支持一下,能上传一下源码吗。   回复  引用  查看    

#6楼 [楼主] 2007-02-26 18:30 Artech      

@钱彦云
问一个简单的问题, 怎样上传源代码。呵呵!!(没有上传过)   回复  引用  查看    

#7楼  2007-02-26 20:38 ColdDog      

@Artech
在管理后台,选择“文件”选项卡,里面就可以上传文件了,限制压缩文件格式   回复  引用  查看    

#8楼  2007-02-27 00:08 Darren Tao [未注册用户]

也是刚开始研究WCF,看到了楼主的例子。非常感谢楼主的辛勤劳动。不过上述代码中有部分问题,就是服务端配置文件中的大小写问题,还有就是behaviorConfiguration=" calculatorBehavior">中多了一个空格,让我好找,呵呵。修改后的配置文件如下:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service name="WCFService.Service.CalculatorService" behaviorConfiguration="calculatorBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8888/GeneralCalculator"/>
</baseAddresses>
</host>
<endpoint address="" binding ="basicHttpBinding" contract="WCFService.Contract.ICalculator"></endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="calculatorBehavior">
<serviceMetadata httpGetEnabled="true" httpGetUrl=""/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>   回复  引用    

#9楼 [楼主] 2007-02-27 10:41 Artech      

@Darren Tao
非常感谢Darren Tao
看来以后我得更加小心谨慎才行。   回复  引用  查看    

#10楼 [楼主] 2007-02-27 10:48 Artech      

@ColdDog
感谢ColdDog。
源代码已上传, 文件名为:Artech.WCFService.zip   回复  引用  查看    

#11楼  2007-02-27 13:01 ColdDog [未注册用户]

呵呵,我下了,学习中,下载地址是:http://www.cnblogs.com/files/artech/Artech.WCFService.zip
  回复  引用    

#12楼  2007-05-20 17:20 Mr.Liu [未注册用户]

我是一个WCF初学者,我用的是window2003 server操作系统,我安装了.net2005,我按照你上面所说的,下载了那两个工具(Net3.0+Extensions for WPF,WCF),其中.net3.0可以安装成功,但另外的一个不能安装,一直提示:"插件安装程序检测不到适当的浏览器安装目录",我该怎么解决??
希望能给我点建议!
谢谢了   回复  引用    

#13楼 [楼主] 2007-05-21 10:57 Artech      

@Mr.Liu
很抱歉,我一直没有在2003上使用WCF,不太清楚具体的原来。如果哪位知道什么原因导致安装失败,请帮助我给以解答,谢谢。

我帮你查查相关资料,有答案通知你。   回复  引用  查看    

#14楼  2007-06-01 09:45 VincnetYin [未注册用户]

关注中.......................   回复  引用    

#15楼  2007-06-13 14:33 妖居      

我第一次运行了Hosting程序,能够正常在IE里面显示Service的信息,但是当时由于疏忽我没有正常结束Hosting,而是使用了IDE里面的Stop按钮。导致此后我再次运行Hosting的时候,运行到ServiceHost calculatorServiceHost = new ServiceHost(typeof(WCFService.Service.CalculatorService), baseUri)的时候会出现The type initializer for 'System.ServiceModel.DiagnosticUtility' threw an exception.异常。我重新启动了机器,IE里面也无法访问Service了,但是问题依旧。

是不是我没有关闭这个ServiceHost造成的呢?
我重启机器了都不行么?
如何通过程序找到正在运行的Service并且关闭呢?   回复  引用  查看    

#16楼 [楼主] 2007-06-13 14:43 Artech      

@妖居
这个倒难到我了,机器重起,Service肯定被关掉了。
会不会是Port被占用?   回复  引用  查看    

#17楼  2007-06-13 14:59 妖居      

@Artech
对不起,是我的配置文件有问题。所以出现了这种情况。:p
不过,如果我加入了配置文件,那么即使使用了new ServiceHost(typeof(CalculatorService), baseUri)构造函数,还是会使用app.config实例化对象的啊。   回复  引用  查看    

#18楼 [楼主] 2007-06-13 16:03 Artech      

@妖居
Config中是默认的配置,你可以通过编程的方式Override它们。
其实推荐的方式把那所有能配置的都放在config里面。在Host的时候只要指定ServerType就可以了:
new ServiceHost(typeof(CalculatorService))   回复  引用  查看    

#19楼  2007-06-26 20:29 Feilenn Li [未注册用户]

感谢,学习中!   回复  引用    

#20楼 [楼主] 2007-06-26 20:47 Artech      

@Feilenn Li
:)   回复  引用  查看    

#21楼  2007-07-23 01:16 hustnn [未注册用户]

The contract name 'Hustnn.WCFService.Contract.ICalculator' could not be found in the list of contracts implemented by the service 'CalculatorService'.我按照在配置文件里面设置来创建host时候,
运行就是有这个异常,能告诉是什么原因吗?谢谢了~   回复  引用    

#22楼 [楼主] 2007-07-23 02:03 Artech      

@hustnn
从Error Message看,是由于你的Host缺少定义了Hustnn.WCFService.Contract.ICalculator的Assembly的Reference引起。   回复  引用  查看    

#23楼  2007-07-23 02:31 hustnn [未注册用户]

我都应用的,是在添加引用添加就行了把?   回复  引用    

#24楼  2007-07-23 02:39 hustnn [未注册用户]

using (ServiceHost calculatorServiceHost = new ServiceHost(typeof(CalculatorService)))异常在这里,calculatorServiceHost值是null,
<configuration>
<system.serviceModel>
<services>
<service name="Hustnn.WCFService.Service.CalculatorService" behaviorConfiguration="calculatorBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8888/GeneralCalculator"/>
</baseAddresses>
</host>
<endpoint address="" binding ="basicHttpBinding" contract="Hustnn.WCFService.Contract.ICalculator"></endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="calculatorBehavior">
<serviceMetadata httpGetEnabled="true" httpGetUrl=""/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
我的config,
下是code
using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Description;
using Hustnn.WCFService.Contract;
using Hustnn.WCFService.Service;

namespace Hustnn.WCFService.HostingByconfig
{
class Program
{
static void Main(string[] args)
{
using (ServiceHost calculatorServiceHost = new ServiceHost(typeof(CalculatorService)))
{
calculatorServiceHost.Opened+=delegate{Console.WriteLine
("calculator service begin to listen via the address:{0}",calculatorServiceHost.BaseAddresses[0].ToString());};
calculatorServiceHost.Open();
Console.Read();
}
}
}
}
对了,我们可以通过edit wcf configuration对话框设置吧
  回复  引用    

#25楼 [楼主] 2007-07-23 07:47 Artech      

@hustnn
最好是通过edit wcf configuration来进行配置。
从Error Message来看,确实是由于不同找到CalculatorService对应的Hustnn.WCFService.Contract.ICalculator。请注意查看:
1. Hustnn.WCFService.Contract.ICalculator运用了ServiceContract/OperationContract.
2. CalculatorService 实现了ICalculator。
3. Host添加了对ICalculator所在Project或 Dll的引用。   回复  引用  查看    

#26楼  2007-07-23 11:28 hustnn [未注册用户]

谢谢啊,搞定了.是我命名空间有问题,using的时候有个地方写错了,有空想多和你交流,向你学习,方便给QQ或者别的什么联系方式~,我QQ287960333
email:287960333   回复  引用    

#27楼 [楼主] 2007-07-23 12:08 Artech      

@hustnn
我的MSN:jiangjinnan#hotmail.com   回复  引用  查看    

#28楼  2007-07-23 13:48 hustnn [未注册用户]

新问题了,创建了client运行程序应该如何?将host与client都设置为启动项吗?
我这样做不行.client有异常,被捕捉了,stacktrace显示了,没有显示加法   回复  引用    

#29楼 [楼主] 2007-07-23 14:09 Artech      

@hustnn
在Solution Explore中,右击你要运行的Project,选择Debug=〉Start New Instance.   回复  引用  查看    

#30楼  2007-07-23 14:15 hustnn [未注册用户]

好了,更正个错误,你的client的endpoint的address与host endpoint 不匹配!
呵呵~问下在config设置的怎么知道我自己写的CalculatorClient这个类呢?
是可以通过名字来标识吗?是不是如果有多个client在config里面就要通过name来标识?   回复  引用    

#31楼 [楼主] 2007-07-23 14:42 Artech      

@hustnn
config不需要知道CalculatorClient,而是你创建了CalculatorClient的时候,会根据Endpoint 的3要素Address,Binding,Contract找到对应的Config。

当然你也可以在Config中为每一个Endpoint起一个Unique Name。关于CalculatorClient的定义,请参考ClientBase的若干Overloaded Constructor。   回复  引用  查看    

#32楼  2007-08-08 18:41 翟羽江      

早就想学WCF了,苦于无处着手,
今天研读了楼主的文章,如醍醐灌顶!
我的WCF未解之谜终于解决了。
感谢!

  回复  引用  查看    

#33楼 [楼主] 2007-08-10 18:15 Artech      

@翟羽江
每次看到象你这样的留言,都让我深受鼓舞。能为读者带来帮助是我写文章的最大动力。
同样谢谢你, 希望和更多朋友多交流,解决心中的困惑。   回复  引用  查看    

#34楼 [楼主] 2007-08-10 18:17 Artech      

@qinjiang
“老师”二字,有点愧不敢当。希望和就WCF作进一步的交流   回复  引用  查看    

#35楼  2007-08-23 16:22 Silent Void      

@Artech

看了这系列的文章,收益颇多,也打算把WCF用在下一个项目中。

但现在遇到一个问题,我要用WCF发布一个EndPoint提供WebService服务(wsHttpBinding,默认的是Message安全机制),客户端想要消费此服务,是不是一定要运行在3.0或3.5上?可不可以在2.0上消费这个WCF服务?譬如我用Add Web References(不是用Add Service References)添加WSDL引用,会自动生成代理类和Config配置,但使用时有点问题:
service1 proxy = new service1();
Uri uri = new Uri("http://localhost/MyServiceUri");
NetworkCredential credential = new NetworkCredential();
credential.UserName = this.tbxUserName.Text;
credential.Password = this.tbxPassword.Text;
proxy.Credentials = credential;
//调用会产生异常:System.Net.WebException: The operation has timed out
proxy.MyOperation1(this.tbxUserName.Text);

btw:使用BasicHttpBinding(默认安全机制为None),可以调用成功。   回复  引用  查看    

#36楼 [楼主] 2007-08-23 16:51 Artech      

@Silent Void
你说的这个问题涉及到一个重要的方面,就是互操作的问题:Interoperability。WCF实现了最新的WS-I Spec(WSE 3.0也一样)。而传统的ASMX实现的仅仅是WS-I Basic Profile 1.1,对于WCF来说,只有BasicHttpBinding是为与那些符合WS-I Basic Profile 1.1的Serice、Client进行互操作而设计的。在2.0的环境下,你通过添加Web Reference实际上是当作传统的ASMX来使用。

不过你可以做一些修改实现和WSE 3.0实现互操作:http://msdn2.microsoft.com/en-us/library/ms730049.aspx   回复  引用  查看    

#37楼  2007-09-10 10:04 EagleFish      

@Artech

首先感谢楼主好文,成为很多人包括我入门WCF的绝对指引。

很多资料都说WCF为跨平台的分布式系统的建立提供了很好的条件,看了楼主的系列文章,所使用的demo的client和server端都是纯的.Net环境。不知楼主能不能专门写篇文章,举一些异构环境下两端用WCF进行通信的例子,相信这对很多要采用WCF进行系统集成的人非常重要:)

再次感谢楼主的文章!   回复  引用  查看    

#38楼 [楼主] 2007-09-10 15:28 Artech      

@EagleFish
谢谢你对WCF系列的关注,你说的问题是一个很实用、也是很宽泛的问题,换句话说是一个Interoperability的问题。我会考虑写一些这样的文章,对WCF,其实我也在一步一步地摸索:)
最近Bruce Zhang的一篇文章谈到了这个问题,你可以看看:http://www.cnblogs.com/wayfarer/archive/2007/09/10/888337.html   回复  引用  查看    

#39楼  2007-09-10 19:15 不就是路过的嘛 [未注册用户]

谢谢你的文章.解决了小弟不少的困惑,感谢!!!!!!!!!!!!   回复  引用    

#40楼 [楼主] 2007-09-10 19:21 Artech      

@不就是路过的嘛
很高兴我的文章能为别人带来价值:)   回复  引用  查看    

#41楼  2007-09-10 19:46 EagleFish      

@Artech

多谢你给出的Bruce Zhang的链接,it helps!

另外,感觉behaviors是WCF中很重要的内容,我们可以用自定义的behavior来对WCF进行扩展。不知Artech怎么理解behavior这个东西?有没有研究过它的典型使用场景和用法?

不好意思,我也是刚开始看WCF相关的东西,并且以前没有过分布式开发的经验,所以感觉困难比较多......   回复  引用  查看    

#42楼  2007-09-11 10:25 EagleFish      

@Artech

再请教老兄一个问题。因为我本地的msdn里面没有关于WCF类库的内容,查什么都需要到msdn online去看,相当不方便。不知老兄是怎么解决这类问题的呢?有没有什么办法一次性批量下载msdn某个目录下的全部内容并和本地的msdn进行整合?

多谢!   回复  引用  查看    

#43楼 [楼主] 2007-09-11 11:05 Artech      

@EagleFish
如果你安装了VS 2008 beta 2,会自动安装一个叫做Microsoft Visual Studio 2008 Beta 2 documentation的文档,安装Windows Vista SDK好像也有有一个类似的文档。里面的结构和MSDN Online Class Library是一样的。   回复  引用  查看    

#44楼  2007-09-20 16:57 笑缘      

@Artech

辛苦了   回复  引用  查看    

#45楼  2007-09-25 11:42 木子文武      

个人任务楼主在讲这样的分布式开发主题的时候加入几张图片可能能更好让人理解内容(^_^)。学习中...   回复  引用  查看    

#46楼  2007-10-08 09:12 jameswei [未注册用户]

有多个接口的话,服务端如何创建 ServiceHost 呢?   回复  引用    

#47楼  2007-10-16 10:26 Alpha and Beta [未注册用户]

非常不错,我也正在学WCF,感谢分享   回复  引用    

#48楼  2007-10-16 10:35 Alpha and Beta [未注册用户]

这里,我想问个问题,作者为什么要在client端建一个类呢?
为什么不通过Add Service Reference把Service ADD进来,直接调用远程类的代理呢?这样不是更加简单   回复  引用    

#49楼  2007-10-16 10:45 Alpha and Beta [未注册用户]

刚发现,原来引用Service,VS2008会自动为你创建一个继承自ClientBase和ICalculate的名为CalculateClient的类
如下:
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public partial class CalculateClient : System.ServiceModel.ClientBase<client.ServiceReference.ICalculate>, client.ServiceReference.ICalculate {

public CalculateClient() {
}

public CalculateClient(string endpointConfigurationName) :
base(endpointConfigurationName) {
}

public CalculateClient(string endpointConfigurationName, string remoteAddress) :
base(endpointConfigurationName, remoteAddress) {
}

public CalculateClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) :
base(endpointConfigurationName, remoteAddress) {
}

public CalculateClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :
base(binding, remoteAddress) {
}

public double add(double a, double b) {
return base.Channel.add(a, b);
}
}   回复  引用    

#50楼 [楼主] 2007-10-16 13:25 Artech      

@Alpha and Beta
WCF在添加Web Reference的时候,会添加必要的Client Code,比如Proxy Client,Contract,Configuration。
这是很方便的方式,但是我不太喜欢。如果想对WCF的原理有一个更好的理解,你可以选择认为添加这些生成的Code,自己编辑Confiruation是自己有更大的控制权。
  回复  引用  查看    

#51楼  2007-10-26 11:35 随风飘散      

谢谢蒋兄,今天犯了个低级错误,竟然在实例化代理类的时候不指定endpointname .   回复  引用  查看    

#52楼 [楼主] 2007-10-26 13:00 Artech      

@随风飘散
呵呵,谁能不犯错^_^   回复  引用  查看    

#53楼  2007-10-26 15:33 winnerzone      

博主犯错误了.配置文件有问题,在2005中的不一样,大小写要注意了.   回复  引用  查看    

#54楼  2007-10-29 22:48 neal1985 [未注册用户]

太好了,带我进入WCF之旅   回复  引用    

#55楼  2007-11-08 11:48 pk的眼泪      

@Artech
如果有多个contract的话,那不是要创建多个host了.
还有配置文件.
不可能把所有的业务都放在同一个contract里吧.
  回复  引用  查看    

#56楼 [楼主] 2007-11-13 13:03 Artech      

@pk的眼泪
一个Host对应一个contract   回复  引用  查看    

#57楼  2007-11-15 14:52 pk的眼泪      

@Artech
怎么调用远程的wcf,
如果wcf中有DataContract层
那么是不是需要同时提供ServerContract.dll & DataContract.dll

调用远程 我有点迷惑,希望指点迷津.3Q.   回复  引用  查看    

#58楼 [楼主] 2007-11-15 15:26 Artech      

@pk的眼泪
Contract是Service Ptrovider和Service Consumer进行交互需要共同遵循的一种契约,你可以共享ServerContract.dll & DataContract.dll,也可以在Client端通过Add Service Reference的方式生成Contract,你也可以自定义Contract,只要能够和Service Side的Contract相互匹配就可以。   回复  引用  查看    

#59楼  2007-11-15 17:12 pk的眼泪      

谢谢.明白了 :)   回复  引用  查看    

#60楼  2007-12-08 19:59 xuyo [未注册用户]

好文。给我知道WCF可以用在Ajax上的,好。   回复  引用    

#61楼  2007-12-15 00:15 学生 [未注册用户]

写的很好啊,学习了哈,如果。希望老师也能够列举一些把wcf应用到具体实例的案例,就好了。   回复  引用    

#62楼  2007-12-16 01:07 chnking      

赞!好文,也开始WCF之旅,以后如遇问题还请博主指教。   回复  引用  查看    

#63楼  2007-12-18 16:20 onekey      

客户端不应该调用服务器端的DLL,只能用代理类。   回复  引用  查看    

#64楼  2007-12-20 13:52 小喳子 [未注册用户]

楼主你好,看了你的文章,那里面的baseaddress是不是一定要是host运行的地址啊   回复  引用    

#65楼 [楼主] 2007-12-21 14:44 Artech      

@小喳子
也可以这么说罢。   回复  引用  查看    

#66楼  2008-01-09 16:54 yilinjun [未注册用户]

博主有指教一下 wcf的用户认证及授权吧.
网上的例子都太小.不成框架.不能做项目.
请指教   回复  引用    

#67楼 [楼主] 2008-01-09 17:05 Artech      

@yilinjun
我正有此打算,正好的工作中需要WCF Security。由于Security是WCF最为复杂的一部分,我打算写一个WCF Security的系列,介绍我对如何在WCF中实现Authentication、Authorization和Securing Comunication的认识。   回复  引用  查看    

#68楼  2008-01-21 13:43 dqy007 [未注册用户]

请问楼主:
如果一个客户端要访问远程一个服务器上的10个服务,客户端和服务器之间有防火墙,那么在防火墙中要设置10个端口通过吗?传统的Com+服务好像只允许一个端口通过就可以 了   回复  引用    

#69楼 [楼主] 2008-01-21 17:52 Artech      

Net.TCP Port Sharing:http://msdn2.microsoft.com/en-us/library/ms734772.aspx   回复  引用  查看    

#70楼  2008-01-22 10:44 dqy007 [未注册用户]

昨天我按你的提供的例子,自己手工一步一步新建工程,(LoginServer,ContractServer,Host)我启动HOST的时候也没有错误,但是就是不监听端口,因为我在浏览器中无法访问 这个服务地址。
我的HOST的app.config代码如下:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="serviceBehavior">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="serviceBehavior" name="LoginServer.LoginAuthenticate">
<endpoint address="Authenticate" binding="basicHttpBinding" bindingConfiguration=""
contract="ContractServer.ILoginAuthenticate" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:6010"" target="_new" rel="nofollow">http://localhost:6010" />
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
</configuration>

Host中代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.ServiceModel ;
using System.ServiceModel.Dispatcher;
namespace Host
{
public partial class ManageService : Form
{
public ManageService()
{
InitializeComponent();

InitializeServer();
}
public void InitializeServer()
{
using (ServiceHost AuthenticateHost = new ServiceHost(typeof(LoginServer.LoginAuthenticate)))
{
AuthenticateHost.Open();

}
}
}
}

ContractServer中的代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Runtime.Serialization;
namespace ContractServer
{ [ServiceContract]
public interface ILoginAuthenticate
{ [OperationContract]
string GetData(int value);
}
}

LoginServer中的代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;

namespace LoginServer
{
public class LoginAuthenticate :ContractServer.ILoginAuthenticate
{
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}


}
}


以上的代码是运行的时候都没有错误 ,但是我在启动Host后,在浏览器输入地址 http://localhost:6010,提示无法显示网页,我想可能是host没有监听这个地址,但是好像没有看出哪里错误呀,麻烦你帮我看看,谢谢
  回复  引用    

#71楼 [楼主] 2008-01-22 11:51 Artech      

@dqy007
加上ServiceMetadata Service Behavior再试试   回复  引用  查看    

#72楼  2008-01-22 12:43 dqy007 [未注册用户]

我的配置文件里有servicebehavior,,还要在哪里加?   回复  引用    

#73楼  2008-01-22 12:47 dqy007 [未注册用户]

<endpoint address="Authenticate" binding="basicHttpBinding" bindingConfiguration=""
contract="ContractServer.ILoginAuthenticate" />
这上面的“address=”后面的名字(Authenticate)是任意填写的的吗?我看过很多其它人的配置也比较随意,好像没有规律 ,它到底有什么用途呢?   回复  引用    

#74楼 [楼主] 2008-01-23 11:12 Artech      

@dqy007
address="Authenticate" , Authenticate因该是Service的相对地址,相对于Base Address   回复  引用  查看    

#75楼  2008-01-23 12:46 dqy007 [未注册用户]

当启动HOST工程后,想在Client端加服务引用 的时候,为什么在客户端工程上点右键,add reference,add web reference,add service reference,这三个引用 就是灰色不可用的???
  回复  引用    

#76楼 [楼主] 2008-01-23 17:54 Artech      

@dqy007
程序在运行,不能修改.   回复  引用  查看    

#77楼  2008-01-24 01:19 tangliangl [未注册用户]

本人系初学者,看到这篇文章后收益匪浅,但是我在运行client端程序时,出现了异常
using (CalculatorClient caluclator = new CalculatorClient()) 产生的caluclator对象是null,我的config文件跟你的是一样的。我怀疑我的配置文件不对,但是对endpoint不太了解。
1).是不是我必须把endpoint配置成host端的一样就ok了?


2).我在用网址访问
http://localhost:8888/GeneralCalculator时可以正常得看到其上发布的服务,这个是
<baseAddresses>
<add baseAddress="http://localhost:8888/GeneralCalculator"/>
</baseAddresses>

endpoint的三个属性如下:
<endpoint address="" binding ="basicHttpBinding" contract="Artech.WCFService.Contract.ICalculator"></endpoint>
这里的address跟http://localhost:8888/GeneralCalculator是什么关系

3).在最后的client端,我们测试是否可以调用host的services时,我们的config文件如下(摘取一段):
<Endpoint Address="http://localhost:8080/WCFService/CalculatorService " Binding="basicHttpBinding" contract="Artech.WCFService.Contract.ICalculator" />

为啥这里的Address跟host端的不一样?我们访问host端的services时不是通过endpoint来访问的么?如果是的话,为啥client和host的Endpoint能不一样呢?

4).client端的endpoint地址:http://localhost:8080/WCFService/CalculatorService 从那里冒出来的?在前面的所有配置的adress和uri里都没见过这个网址。是不是工程中的那个asp网站?   回复  引用    

#78楼  2008-01-24 08:55 dqy007 [未注册用户]

@Artech
如果不启动HOST,我怎么加客户端的契约呀,我的是VS2008的,不会还要工具生成吧??听说只要add service reference就可以了   回复  引用    

#79楼  2008-01-24 14:39 tangliangl [未注册用户]

@tangliangl
我把client配置文件改成这个就不再有异常了,原来是要注意大小写的!

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<client>
<endpoint address="http://localhost:8888/GeneralCalculator" binding="basicHttpBinding"
contract="Artech.WCFService.Contract.ICalculator" />
</client>
</system.serviceModel>
</configuration>   回复  引用    

#80楼  2008-01-24 16:19 d [未注册用户]

文章不错 ,顶   回复  引用    

#81楼  2008-02-16 15:32 你好aaaa [未注册用户]

文章很好很详细啊!   回复  引用    

#82楼  2008-02-21 09:15 zzz [未注册用户]

谢谢楼主的文章。有个问题请教一下:我写了个WCF例子,客户端调用服务时,如果要求返回少量的List<string>,程序正常,如果要求返回大量的List<string>时则出错:“读取管道时出错: 管道已结束。 (109、0x6d)。” 主要代码如下:
1)ServiceContract及其实现的代码:

[ServiceContract]
public interface IService //接口
{
[OperationContract]
List<string> GetStringList(int numToGet); //返回的是List<string> , 泛型
}

public class Service : IService //实现
{
public List<string> GetStringList(int numToGet)
{
List<string> list = new List<string>();
for (int i = 0; i < numToGet; i++)
{
list.Add(string.Format("这是第{0}个字符串/r/n", i));
}
return list;
}
}

internal class MyServiceHost
{
internal static ServiceHost serviceHost = null;

internal static void StartService()
{
Uri baseAddress = new Uri("net.pipe://localhost/WCFService/Service");
NetNamedPipeBinding binding = new NetNamedPipeBinding();
binding.MaxReceivedMessageSize = 65536 * 1000;
serviceHost = new ServiceHost(typeof(Service), baseAddress);
serviceHost.AddServiceEndpoint(typeof(WCFService.IService), binding, "");
ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
behavior.HttpGetEnabled = true;
behavior.HttpGetUrl = new Uri("http://localhost:8001/");
serviceHost.Description.Behaviors.Add(behavior);
serviceHost.Open();
}

internal static void StopService()
{
if (serviceHost.State != CommunicationState.Closed)
serviceHost.Close();
}
public static void Main() //控制台Main
{
StartService();
Console.WriteLine("Service Start.....");
Console.ReadLine();
StopService();
}
}


2)客户端主要代码:
try
{
NetNamedPipeBinding binding = new NetNamedPipeBinding();
binding.MaxReceivedMessageSize = 65536*1000;
ServiceClient proxy = new ServiceClient(binding,
new EndpointAddress("net.pipe://localhost/WCFService/Service"));
List<string> list = proxy.GetStringList(100000); //已通过VS将集合类型映射为List<T>
//StringBuilder sb = new StringBuilder();
//foreach (string s in list)
//{
// sb.Append(s);
//}

//textBox1.Text = sb.ToString();
}
catch (CommunicationException ex)
{
textBox1.Text = "错误::" + ex.Message;
}

问题出在这一行:List<string> list = proxy.GetStringList(100000);
如果这一行中的GetStringList()的参数值改小一点,如10000,则程序正常运行,如果大一点则出错(不是MaxReceivedMessageSize值太小的问题),请问应该设置哪些属性才能解决?先谢了!   回复  引用    

#83楼 [楼主] 2008-02-21 10:44 Artech      

@zzz
可能是操作超时造成,修改Binding Timeout相关的配置试试。   回复  引用  查看    

#84楼  2008-02-21 10:49 zzz [未注册用户]

这么快就得到回复,谢谢楼主!!我试试。   回复  引用    

#85楼  2008-02-21 10:55 zzz [未注册用户]

我对Service和Client端的binding都作了如下配置:
binding.OpenTimeout = new TimeSpan(1, 10, 0);
binding.CloseTimeout = new TimeSpan(1, 10, 0);
binding.SendTimeout = new TimeSpan(1, 10, 0);
binding.ReceiveTimeout = new TimeSpan(1, 10, 0);
结果还是显示“读取管道时出错: 管道已结束。 (109、0x6d)”。   回复  引用    

#86楼  2008-02-21 11:26 zzz [未注册用户]

刚才在Service的app.config中加入了trace:
<system.diagnostics>
<sources>
<source name="System.ServiceModel"
switchValue="Information, ActivityTracing"
propagateActivity="true">
<listeners>
<add name="traceListener"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData= "d:/temp/WCFTraces.xml" />
</listeners>
</source>
</sources>
</system.diagnostics>

结果d:/temp/WCFTraces.xml有如下错误信息:
System.ServiceModel.CommunicationException: 尝试对参数 http://tempuri.org/ 进行序列化时出错: GetStringListResult。InnerException 消息是“对象图中可以序列化或反序列化的项目数目上限为“65536”。请更改对象图或增加 MaxItemsInObjectGraph 的配额。 ” 。有关详细信息,请参见 InnerException。
  回复  引用    

#87楼  2008-02-21 11:47 zzz [未注册用户]

不好意思,再请教一下:
trace是刚从一个帖子看到的,我不知道怎么使用它生成的信息,不知道我的代码出错与上面的WCFTraces.xml里的错误信息有没有关系。如果有,怎么更改对角图?怎么设置MaxItemsInObjectGraph?Google 了一下,没有看到MaxItemsInObjectGraph 的例子,只好再来麻烦楼主了。   回复  引用    

#88楼  2008-02-21 12:01 zzz [未注册用户]

sorry,刚才GOOGLE时拼错了MaxItemsInObjectGraph. 好象有例子,我研究一下先,如果不行再麻烦您了。再次感谢!   回复  引用    

#89楼  2008-02-27 09:29 千年之夏 [未注册用户]

楼主的这个系列帮了大忙了   回复  引用    

#90楼  2008-02-28 13:13 人民币 [未注册用户]

最近正在学习。。。   回复  引用    

#91楼  2008-03-02 12:35 panda33 [未注册用户]

想请教一下楼主,WCF是不是一定要在.NET2008的环境下运行的??
如果我只装.Net Frame 3.0,然后在.Net2005或者在.Net2003下边编写相应的程序,是否可以呢?
感觉好似不可以,至少低版本的vs没有支持匿名访问、LinQ(好在楼主在这一单系列没用到)。
麻烦楼主给予解答,谢谢!   回复  引用    

#92楼 [楼主] 2008-03-03 12:17 Artech      

@panda33
在VS 2005下,需要安装VS Extension for WCF&WPF   回复  引用  查看    

#93楼  2008-03-10 19:45 kingly [未注册用户]

真心感谢楼主,学习中。。。。。。谢谢   回复  引用    

#94楼  2008-03-12 13:37 Howard Queen      

敬仰!学习!
原以为"WCF"是类似"MFC"等早期c++的应用(平台)术语,
原来是新技术啊!
敬仰!学习!   回复  引用  查看    

#95楼  2008-03-18 14:41 伊凡1983 [未注册用户]

不错不错,受益菲浅
学习中   回复  引用    

#96楼  2008-03-20 15:40 人民币 [未注册用户]

怎么迟迟不见楼主关于wcf安全系列的文章呢   回复  引用    

#97楼 [楼主] 2008-03-24 08:44 Artech      

@人民币
最近实在太忙, 心有余而力不足啊^_^   回复  引用  查看    

#98楼  2008-04-01 18:28 liujinghua [未注册用户]

gsag   回复  引用    

#99楼  2008-04-01 18:29 liujinghua [未注册用户]

@liujinghua
--引用--------------------------------------------------
liujinghua: gsag
--------------------------------------------------------
--引用--------------------------------------------------
liujinghua: gsag
--------------------------------------------------------
  回复  引用    

#100楼  2008-04-15 17:26 我不是老虎 [未注册用户]

太强了,强悍的一塌糊涂   回复  引用    

#101楼 [楼主] 2008-04-16 14:48 Artech      

@我不是老虎
^_^   回复  引用  查看    

#102楼  2008-04-18 16:49 good man      

有一点很深啊,我初学者有一点看不懂哟
支持   回复  引用  查看    

#103楼  2008-04-24 23:07 chenyl [未注册用户]

网页很不错~~   回复  引用    

#104楼  2008-04-26 19:14 fldastk [未注册用户]

楼主你好,看了你的文章,我学到了很多东西,对于我做的项目也有很大帮助。我准备在论文当中引用了《我的WCF之旅》中的部分文段,并在论文的参考文献中注明来自此blog。谢谢^_^

[2] Artech, 我的WCF之旅[EB/OL], http://www.cnblogs.com/artech/archive/2007/02/26/656901.html, 2007-02-26
  回复  引用    

#105楼  2008-04-28 10:47 镜涛      

当calculatorServiceHost.Open();被调用之后,系统会查看calculatorServiceHost对应的Service的类型,结果发现它的类型是Artech.WCFService.Service. CalculatorService(在ServiceHost被创建时最为第一个传入参数);然后会在config文件中Services部分中找name属性和这个Service type相匹配,找到之后,把它host进来,然后添加它在配置文件中定义的所有的Endpoint,并设置在配置文件中定义的所有Binding 以及 Behavior。

我建的wcf项目下有一个webconfig文件,里面同样有service的配置信息,可是我用
using (ServiceHost host = new ServiceHost(typeof(WCFRuby.Service1)))
{
host.Open();
Console.Read();
}
测试时。出现错误:Service 'WCFRuby.Service1' has zero application (non-infrastructure) endpoints. This might be because no configuration file was found for your application, or because no service element matching the service name could be found in the configuration file, or because no endpoints were defined in the service element.
配置文件:<system.serviceModel>
<services>
<service name="WCFRuby.Service1" behaviorConfiguration="WCFRuby.Service1Behavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:1111/GetData"/>
</baseAddresses>
</host>
<!-- Service Endpoints -->
<endpoint address="" binding="basicHttpBinding" contract="WCFRuby.IService1">
<!--
Upon deployment, the following identity element should be removed or replaced to reflect the
identity under which the deployed service runs. If removed, WCF will infer an appropriate identity
automatically.
-->
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="WCFRuby.Service1Behavior">
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true" httpGetUrl=""/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
不知道什么问题。请指导!
  回复  引用  查看    

#106楼  2008-05-07 10:51 Cdong [未注册用户]

hello Artech,如果是client端是.NET 1.1,那该如何创建Client端程序?
谢谢!   回复  引用    

#107楼 [楼主] 2008-05-07 12:28 Artech      

@Cdong
可以采用Web Service的方式,添加Web Reference!   回复  引用  查看    

#108楼  2008-05-16 10:24 Henllyee Cui      

看了许多篇关于wcf的文章,感觉你讲解得是最好的。   回复  引用  查看    

#109楼  2008-06-02 21:08 cc@ [未注册用户]

弱弱的请教博主,vs2008建立项目时,建立wcf项目和建立普通c#项目有什么不同,这个解决方案里面的5个项目是全部用普通c#项目好还是用wcf项目好?还有您的那个网站的地址是不是部署到iis后的地址?小弟刚刚接触。net不就,忘不吝指教,谢谢!   回复  引用    

#110楼 [楼主] 2008-06-03 10:22 Artech      

@cc@
wcf项目和建立普通c#项目没有本质的区别,它会为你添加一些Reference, 额外的文件比如service.svc,等等。 我习惯创建一个普通的Project,然后按需添加Reference,Configuration等等。
如果采用IIS Hosing, 需要创建一个svc文件,该文件的地址就是Service的地址。
  回复  引用  查看    

#111楼  2008-06-05 09:34 Henllyee Cui      

楼主有问题请教下,我的wcf程序中,当hosting启动后,我想用代理的方式在客户端添加服务应用。可是当hosting启动后我的vs中的client的添加服务应用是灰色的,不好添加服务引用。
我的vs版本是2008中文team的,难道是我的vs是盗版的原因
  回复  引用  查看    

#112楼  2008-06-05 11:04 haibo yan [未注册用户]

楼主的定义有问题吧,Contract有四种,你说的应该是Service Contract   回复  引用    

#113楼  2008-06-05 16:07 cc@      

多谢博主赐教,看了博主很多wcf的文章,受益很多,现在唯一觉得有难度的是config文件,请问下楼主有没有自动生成config文件的工具,还有自动生成客户端的软件哪里有下,在msdn搜了下,但是不知道名字。   回复  引用  查看    

#114楼  2008-06-05 16:25 cc@      

还想请问下博主wcf中有没有p2p的内容?如果没有,在。net平台下用什么来做p2p好?   回复  引用  查看    

#115楼 [楼主] 2008-06-05 18:48 Artech      

@cc@
VS 2005 & VS 2008都自带了配置工具: Tools/WCF Service Configuration Editor
  回复  引用  查看    

#116楼  2008-06-18 13:33 Johnhormy [未注册用户]

@Henllyee Cui
调试的时候不能添加引用啊。。去Bin/debug目录跑服务程序吧。。   回复  引用    

#117楼  2008-07-02 18:02 Fishman      

谢谢 很好的文章 受教育了 :)   回复  引用  查看    

#118楼  2008-07-10 10:36 finix      

迟到了,才开始学啊   回复  引用  查看    

#119楼  2008-07-22 14:04 chenzt [未注册用户]

刚开始接触WCF,有个菜鸟级的问题想请教一下,就是关于编码方式的问题。Message的编码方式——text/XML, binary,MTOM,我想知道,这几种方式在
.NET Framework 平台下只能通过WCF实现么?还是也有别的方法实现?这个问题实在太菜了 呵呵   回复  引用    

#120楼 [楼主] 2008-07-24 09:13 Artech      

@chenzt
text/XML, binary,MTOM仅仅是一种Message Encoding方式而已,和WCF没有必然的联系。 WSE也可以使用。   回复  引用  查看    

#121楼  2008-07-24 15:12 随风一夜 [未注册用户]

问个问题..在class CalculatorClient:ClientBase<ICalculator>,ICalculator句话中,ClientBase<ICalculator>是什么意思.为什么继承这个类的时候需要加<ICalculator>,和普通的继承有什么区别??   回复  引用    

#122楼  2008-08-28 00:46 edrp.cn      

从网找了那么多资料,看了你的文章让我受益非浅,谢谢!   回复  引用  查看    

#123楼 [楼主] 2008-08-28 10:02 Artech      

@edrp.cn
欢迎常来:)   回复  引用  查看    

#124楼 [楼主] 2008-08-28 10:03 Artech      

@随风一夜
Generic type的基本用法呀。   回复  引用  查看    

#125楼  2008-08-30 10:31 徐沈      

在IE中输入Metadata Endpoint的Address来测试Service的可访问性的时候
IE总是显示该页无法显示
是什么原因呢??
还请不吝赐教   回复  引用  查看    

#126楼  2008-08-31 16:44 James_net [未注册用户]

看了楼主的关于WCF文章,写得很详细,辛苦了呵呵
最近项目中也用到了WCF,在Service中配置log4net,最先的做法是在Service启动时加载log4net配置,运行一切正常。但是后来把log4net分离出去做为一个静态类,也就是在命名空间namespace Artech.WCFService.Service中加了一个静态类来专门负责加载log4net,程序中使用log就出报错了
:The server was unable to process the request due to an internal error.
楼主能解释下原因吗?
  回复  引用    

#127楼  2008-08-31 21:53 edrp.cn      

LZ,我又回来了,请教一个问题,如果WCF的Service的服务不运行,那么客户端就无法调用WCF了?那在开发一个多层的B/S应用的话,那是不是要把WCF做为服务运行呢? 如果创建一个ASP.NET MVC应用程序,如何处理MCF呢?是做为一个单独的类库?然后在配置文件中本来配置Endpoint?最近学的多了,也是越来越糊涂了   回复  引用  查看    

#128楼 [楼主] 2008-09-01 11:44 Artech      

@徐沈
ServiceMetadataBehavior配置是否正确??   回复  引用  查看    

#129楼 [楼主] 2008-09-01 11:44 Artech      

@James_net
对Log4Net没有深入的研究,很抱歉!   回复  引用  查看    

#130楼 [楼主] 2008-09-01 11:47 Artech      

@edrp.cn
一般来讲,WCF和你Client应用类型,因为WCF创建的是service, service不是独立的、自治的,不依赖于service consumer。   回复  引用  查看    

#131楼  2008-09-06 12:02 Joanna [未注册用户]

博主你好,我也是跟着您的示例初次学习WCF的,先说声您辛苦了!
在学习中遇到一个问题:在配置app.config之前,host成功了,可当配置了web.config以后就总是提示有如下错误:
“System.ServiceModel.DiagnosticUtility”的类型初始值设定项引发异常。
我的配置文件是这样的:
<system.ServiceModel>
<Services>
<Service name="Joanna.WCFService.Service.CalculatorService" behaviorConfiguration="calculatorBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8080/calculator"/>
</baseAddresses>
</host>
<Endpoint Address="" Binding ="basicHttpBinding" contract="Joanna.WCFService.Contract.ICalculator"></Endpoint>
</Service>
</Services>
<behaviors>
<ServiceBehaviors>
<behavior name="calculatorBehavior" >
<ServiceMetadata httpGetEnabled="true" />
</behavior>
</ServiceBehaviors>
</behaviors>

</system.ServiceModel>

盼回复!谢谢...
  回复  引用    

#132楼  2008-09-06 14:21 Joanna [未注册用户]

找到问题了..原来是配置文件中的大小写问题...   回复  引用    

#133楼 [楼主] 2008-09-08 09:24 Artech      

@Joanna
呵呵,这种错误很不容易发现:)   回复  引用  查看    

#134楼  2008-09-08 09:48 Joanna [未注册用户]

另外有一个疑问:那个代理类在布署的时候是放在客户端还是放在服务端啊?我怎么发觉都可以啊?还是我的理解是错误的?我是这样测试的:
我用vs创建了一个解决方案A,里面包括了contract,service,proxy.然后host了.
然后我又用vs新创建另一个解决方案B(也就是打开两个vs,两个进程互不相干).然后我在B中添加了service reference,然后居然就可以直接访问A中的proxy了(即CalulatorClient)...这是不是说明proxy是可以放在服务端的呢?还是我的理解有错误?   回复  引用    

#135楼 [楼主] 2008-09-08 10:09 Artech      

@Joanna
代理,顾名思义,就是在client端对service的代理!   回复  引用  查看    

#136楼  2008-09-08 10:26 Joanna [未注册用户]

嗯.谢谢您的回复!
我的意思是说:这个代理是在服务端进行创建,然后各个客户端通过add service reference引用就可以了,还是说在服务端只要创建contract,service,而这个proxy需要由每个客户端自己去创建?我原以为是后者..但经我那么测试下来却发觉似乎可以由服务端来创建,如果有多个子系统需要用到这个服务,岂不是省省力气了.....我不知道是不是因为我的测试的方式或理解是错的.   回复  引用    

#137楼  2008-09-08 10:51 Joanna [未注册用户]

对不起..应该是我搞错了才对....
我将那个Joanna.WCFService.Client(对应了您给的这个示例的Artech.WCTService.Client从A项目中删除)...然后在B项目中add service reference....但是我发觉vs在我定义的命名空间中自动创建了CalcuatorClient,并有好几个重载...您给的示例是手动创建代理类,而在vs中是可以通过这种方式自动创建代理类,是这样吗?....看来是我错的离谱了...呵呵..并谢谢您!   回复  引用    

#138楼 [楼主] 2008-09-08 10:58 Artech      

@Joanna
:)
  回复  引用  查看    

#139楼  2008-09-09 16:24 啤酒花 [未注册用户]

楼主 我现在在做一个wcf的项目 现在遇到2个难题
1: 我现在需要将client的端也host 到 IIS,然后在给别人调用.
2: Server端口 能否主动的象client请求消息,而不是callback.   回复  引用    

#140楼 [楼主] 2008-09-12 09:33 Artech      

@啤酒花
不明白你说的client host什么意思。你的意思是Client也是一个WCF Service,该Service调用另一个Service?
Service只能以Callback的方式调用Client。如何Client也是一个Service,那么这相当与Service和Client的角色对调。和调用一个普通的service没有分别!   回复  引用  查看    

#141楼  2008-09-12 11:46 我是啤酒花 [未注册用户]

1.恩,我的意思是client本身会自己在调用一个service,我想,如果有很多机需要连接service的时候哦会加大service的压力,我现在的client端实际上是个服务的代理,有这个clint统一的创建一个连接去连接服务器(甚至有些情况数据可能就在本地),所以我就想client 能否直接host在IIS 的原因。
2.Service主动调用client端的方法我大概想了一下,为每个连接对象创建一个join方法,然后将join回调添加到service的一个多播委托中,当需要的时候去整这个委托列表。
***************************************
我现在又遇到了一个新问题了。
1 我把Service host在本地的一个虚拟机上的IIS上。
2 然后client 直接在IE上去请求这个服务地址 是正常的,而我用svcutil.exe去访问这个wsdl 会抛出"远程服务器返回意外相应<407> Proxy Authentication Required <The ISA Server requires authorization to fulffill the request. Access to the Web Proxy filter is denied"这个异常

我的网络环境是在公司估计用的ISA代理,然后我本地机没加到域中,而是用的另外一个代理来上网的
我client代码是
string endPoint = System.Configuration.ConfigurationSettings.AppSettings["EndPointName"];
ChannelFactory<IContractService> clinet = new ChannelFactory<IContractService>("WSHttpBinding_IContractService");

clinet.Credentials.UserName.UserName = "user";
clinet.Credentials.UserName.Password = "password";


IContractService icontract = clinet.CreateChannel();
这里的用户名 和密码是我的域帐户 但是还是出现这个异常,而我们同事的加到域中的机器却访问正常.   回复  引用    

#142楼  2008-09-12 15:12 我是啤酒花 [未注册用户]

string endPoint = System.Configuration.ConfigurationSettings.AppSettings["EndPointName"];
ChannelFactory<IContractService> clinet = new ChannelFactory<IContractService>("WSHttpBinding_IContractService");

System.Net.WebProxy proxy = new System.Net.WebProxy();
proxy.Credentials = new System.Net.NetworkCredential("huyb@hubei.jztey.com", "nowait", "hubei.jztey.com");

这个proxy 我改望那个地方赋值呀。   回复  引用    

#143楼  2008-09-13 19:29 qiuyun8m [未注册用户]

受教了   回复  引用    

#144楼 [楼主] 2008-09-14 17:09 Artech      

@我是啤酒花
按照SOA原理来讲,并没有绝对的Client和Server说发,一个service仅可以为别人提供功能的实现,也可以调用其它的service。所以在一个具体的场景中,只有服务的提供者和服务的消费者之分。
1. 对于你host到IIS中的service来说,它可以看成是一个中介服务,对最终用户他是服务的提供者,对于最终的服务来讲,它是服务的消费者。所以,你可以向一般的服务一样将其host到IIS,这和一般的service没有本质的区别,至于具体实现则通过调用最终的service,这和一般的service调用也没有本质的区别。
2.对client的多播也是可以实现的,可以参考我的例子:http://www.cnblogs.com/artech/archive/2008/08/04/1259607.html   回复  引用  查看    

#145楼 [楼主] 2008-09-14 17:09 Artech      

@我是啤酒花
可以设置一个有效的Domain账户试试:Domain name/UserAccount.   回复  引用  查看    

#146楼 [楼主] 2008-09-14 17:10 Artech      

@qiuyun8m
欢迎常来!   回复  引用  查看    

#147楼  2008-09-22 22:44 BenBen123 [未注册用户]

各位大侠,为什么在运行客户端的时候会出现如下异常:Could not connect to http://localhost:8888/generalCalculator. Tcp error code 10061: No connection could be made because the target machine actively refused it 127.0.0.1:8888   回复  引用    

#148楼  2008-09-24 09:26 1490 [未注册用户]

好文!!
就是有点不中不西的。
建议非技术关键词都用中文。
参考Msdn一些文章
  回复  引用    

#149楼 [楼主] 2008-09-24 09:31 Artech      

@1490
我很少看中文方面的文章,有些术语不知道怎么翻译,翻译过来也觉得很别扭,直接使用英文我觉得更好!   回复  引用  查看    

#150楼  2008-10-04 06:38 ganquan [未注册用户]

http://localhost/WCFService这个项目能不能讲解几句?这项目里怎么搞了这么多个类?搞这么复杂?   回复  引用    

#151楼 [楼主] 2008-10-04 08:36 Artech      

@ganquan
复杂?这些都是一个完整的WCF应用基本的要素:Contract、Service、Host、Client   回复  引用  查看    

#152楼  2008-10-07 11:05 @152 [未注册用户]

LZ,麻烦把上面的改下吧   回复  引用    

#153楼  2008-10-07 11:06 @152 [未注册用户]

教程是好
就是错漏百出啊,害人不浅啊   回复  引用    

#154楼 [楼主] 2008-10-07 12:16 Artech      

@@152
你说的是那里,还请明示!   回复  引用  查看    

#155楼  2008-10-07 16:40 hehee [未注册用户]

@@152
大概说的是Hosting那块的那个App.config的内容吧,里面有一些属性的大小写不对,还少了几个结束标签,直接copy是用不成的,建议lz更新一下 Y_Y   回复  引用    

#156楼  2008-10-08 23:10 @Artech您好 [未注册用户]

@Artech
和前面的很多读者一样,看了您的好文,激动不已呀,这是我看过最好的引导初学者探索一门新技术的指引。WCF系列只看了第一篇就受益匪浅,有如拨开乌云见晴天啊!
感谢您的辛勤劳动!   回复  引用    

#157楼 [楼主] 2008-10-09 12:07 Artech      

@@152
可以下载Source Code!   回复  引用  查看    

#158楼  2008-10-09 15:14 airwolf2026      

@152可能这个同学说的是类似这样的
<Endpoint Address="http://localhost:8080/WCFService/CalculatorService " Binding="basicHttpBinding" contract="Artech.WCFService.Contract.ICalculator" />


吧.这个如果从文章看下来,会让初学者觉得莫名其妙.呵呵.(其实是没有错的,只是突然有个跳跃了)

俺今天开始学习楼主这个系列哈.   回复  引用  查看    

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 内容概要 《计算机试卷1》是一份综合性的计算机基础和应用测试卷,涵盖了计算机硬件、软件、操作系统、网络、多媒体技术等多个领域的知识点。试卷包括单选题和操作应用两大类,单选题部分测试学生对计算机基础知识的掌握,操作应用部分则评估学生对计算机应用软件的实际操作能力。 ### 适用人群 本试卷适用于: - 计算机专业或信息技术相关专业的学生,用于课程学习或考试复习。 - 准备计算机等级考试或职业资格认证的人士,作为实战演练材料。 - 对计算机操作有兴趣的自学者,用于提升个人计算机应用技能。 - 计算机基础教育工作者,作为教学资源或出题参考。 ### 使用场景及目标 1. **学习评估**:作为学校或教育机构对学生计算机基础知识和应用技能的评估工具。 2. **自学测试**:供个人自学者检验自己对计算机知识的掌握程度和操作熟练度。 3. **职业发展**:帮助职场人士通过实际操作练习,提升计算机应用能力,增强工作竞争力。 4. **教学资源**:教师可以用于课堂教学,作为教学内容的补充或学生的课后练习。 5. **竞赛准备**:适合准备计算机相关竞赛的学生,作为强化训练和技能检测的材料。 试卷的目标是通过系统性的题目设计,帮助学生全面复习和巩固计算机基础知识,同时通过实际操作题目,提高学生解决实际问题的能力。通过本试卷的学习与练习,学生将能够更加深入地理解计算机的工作原理,掌握常用软件的使用方法,为未来的学术或职业生涯打下坚实的基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值