Artech

Develop every application as an art using the most suitable technologies!

常用链接

统计

积分与排名

网上邻居

我的博文系列

最新评论

[原创]我的WCF之旅(2):Endpoint Overview

WCF实际上是构建了一个框架,这个框架实现了在互联系统中各个Application之间如何通信。使得Developers和Architect在构建分布式系统中,无需在考虑如何去实现通信相关的问题,更加关注与系统的业务逻辑本身。而在WCF Infrastructure中,各个Application之间的通信是由Endpoint来实现的。

Endpoint的结构

Endpoint包含以下4个对象:

  • Address: Address通过一个URI唯一地标识一个Endpoint,并告诉潜在的WCF service的调用者如何找到这个Endpoint。所以Address解决了Where to locate the WCF Service?
  • Binding: Binding实现在Client和Service通信的所有底层细节。比如Client与Service之间传递的Message是如何编码的——text/XML, binary,MTOM;这种Message的传递是采用的哪种Transport——TCP, Http, Named Pipe, MSMQ; 以及采用怎样的机制解决Secure Messaging的问题——SSL,Message Level Security。所以Binding解决的是How to communicate with service?
  • Contract: Contract的主要的作用是暴露某个WCF Service所提供的所有有效的Functionality。从Message Exchange的层面上讲,Contract实际上是抱每个Operation转化成为相对应的Message Exchange Pattern——MEP(Request/Response; One-way; Duplex)。所以Contract解决的是What functionalities do the Service provide?
  •  Behavior: Behavior的主要作用是定制Endpoint在运行时的一些必要的Behavior。比如Service 回调Client的Timeout;Client采用的Credential type;以及是否支持Transaction等。

当我们Host一个WCF Service的时候,我们必须给他定义一个或多个Endpoint,然后service通过这个定义的Endpoint进行监听来自Client端的请求。当我们的Application需要调用这个Service的时候,因为Client 和Service是通过Endpoint的进行通信的, 所以我们必须为我们的Application定义Client端的Endpoint。只有当Client的Endpoint和Service端某个Endpoint相互匹配(Service端可以为一个Service定义多个Endpoint),Client端的请求才能被Service端监听到。也就是说,我们只有在Client具有一个与Service端完全匹配的Endpoint,我们才能调用这个Service。而这种匹配是比较严格的,比如从匹配Address方面,Client端和Service端的Endpoint Address不仅仅在URI上要完全匹配Service, 他们的Headers也需要相互匹配。对于Binding, 一般地,Client需要有一个与Service端完全一样的Binding,他们之间才能通信。 

Sample

首先给一个Sample,以便我们对在WCF Service Aplication中如何定义Endpoint有一个感性的认识。整个Solution的结构参照下图,我的上一篇Blog([原创]我的WCF之旅(1):创建一个简单的WCF程序 )中有详细的介绍。你也可以通过后面的Link下载相应的Source Code(http://www.cnblogs.com/files/artech/Artech.WCFService.zip


1. Service Contract:Artech..WCfService.Contract/ServiceContract/IGeneralCalculator.cs

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

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

}

2. Service: Artech.WCFSerice.Service/GeneralCalculatorService.cs

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

using Artech.WCFService.Contract;

namespace Artech.WCFService.Service
{
    
public class GeneralCalculatorService:IGeneralCalculator
    
{
        
IGeneralCalculator Members
    }

}


3. Hosting: Artech.WCFService.Hosting/Program.cs

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)
        
{
            
//HostCalculatorServiceViaCode();
            HostCalculatorSerivceViaConfiguration();
        }


        
/// <summary>
        
/// Hosting a service using managed code without any configuraiton information. 
        
/// Please note that the related configuration data should be removed before calling the method.
        
/// </summary>

        static void HostCalculatorServiceViaCode()
        
{
            Uri httpBaseAddress 
= new Uri("http://localhost:8888/generalCalculator");
            Uri tcpBaseAddress 
= new Uri("net.tcp://localhost:9999/generalCalculator");
            
            
using (ServiceHost calculatorSerivceHost = new ServiceHost(typeof(GeneralCalculatorService), httpBaseAddress, tcpBaseAddress))
            
{           
                BasicHttpBinding httpBinding 
= new BasicHttpBinding();
                NetTcpBinding tcpBinding 
= new NetTcpBinding();

                calculatorSerivceHost.AddServiceEndpoint(
typeof(IGeneralCalculator), httpBinding, string.Empty);
                calculatorSerivceHost.AddServiceEndpoint(
typeof(IGeneralCalculator), tcpBinding, string.Empty);

                ServiceMetadataBehavior behavior 
= calculatorSerivceHost.Description.Behaviors.Find<ServiceMetadataBehavior>();
                
{
                    
if(behavior == null)
                    
{
                        behavior 
= new ServiceMetadataBehavior();
                        behavior.HttpGetEnabled 
= true;
                        calculatorSerivceHost.Description.Behaviors.Add(behavior);
                    }

                    
else
                    
{
                        behavior.HttpGetEnabled 
= true;
                    }

                }


                calculatorSerivceHost.Opened 
+= delegate
                
{
                    Console.WriteLine(
"Calculator Service has begun to listen  ");
                }
;

                calculatorSerivceHost.Open();

                Console.Read();
            }

        }


        
static void HostCalculatorSerivceViaConfiguration()
        
{
            
using (ServiceHost calculatorSerivceHost = new ServiceHost(typeof(GeneralCalculatorService)))
            
{               
                calculatorSerivceHost.Opened 
+= delegate
                
{
                    Console.WriteLine(
"Calculator Service has begun to listen  ");
                }
;

                calculatorSerivceHost.Open();

                Console.Read();
            }

        }
        
    }

}

4. Service.svc: http://localhost/WCFService/ GeneralCalculatorService.svc

<%@ ServiceHost Language="C#" Debug="true" Service="Artech.WCFService.Service.GeneralCalculatorService" %>

5. Client: Artech.WCFService.Client/ GeneralCalculatorClient.cs & Program.cs 

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 GeneralCalculatorClient:ClientBase<IGeneralCalculator>,IGeneralCalculator
    
{
        
public GeneralCalculatorClient()
            : 
base()
        
{ }

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

        
public GeneralCalculatorClient(Binding binding, EndpointAddress address)
            : 
base(binding, address)
        
{ }

        
IGeneralCalculator Members
    }

}


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()
        
{
            
try
            
{
                
//InvocateCalclatorServiceViaCode();

                InvocateCalclatorServiceViaConfiguration();
            }

            
catch (Exception ex)
            
{
                Console.WriteLine(ex.Message);
            }


            Console.Read();    
        }


        
static void InvocateCalclatorServiceViaCode()
        
{
            Binding httpBinding 
= new BasicHttpBinding();
            Binding tcpBinding 
= new NetTcpBinding();

            EndpointAddress httpAddress 
= new EndpointAddress("http://localhost:8888/generalCalculator");
            EndpointAddress tcpAddress 
= new EndpointAddress("net.tcp://localhost:9999/generalCalculator");
            EndpointAddress httpAddress_iisHost 
= new EndpointAddress("http://localhost/wcfservice/GeneralCalculatorService.svc");

            Console.WriteLine(
"Invocate self-host calculator service ");

            
Invocate Self-host service

            Console.WriteLine(
"\n\nInvocate IIS-host calculator service ");

            
Invocate IIS-host service
        }


        
static void InvocateCalclatorServiceViaConfiguration()
        
{
            Console.WriteLine(
"Invocate self-host calculator service ");

            
Invocate Self-host service

            Console.WriteLine(
"\n\nInvocate IIS-host calculator service ");

           
Invocate IIS-host service
        }

    }

}


6. Self-Hosting Configuration: Artech.WCFService.Hosting/App.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  
    
<system.serviceModel>
        
<behaviors>
            
<serviceBehaviors>
                
<behavior name="calculatorServieBehavior">
                    
<serviceMetadata httpGetEnabled="true" />
                
</behavior>
            
</serviceBehaviors>
        
</behaviors>
      
        
<services>
            
<service behaviorConfiguration="calculatorServieBehavior" name="Artech.WCFService.Service.GeneralCalculatorService">
                 
<endpoint address="" binding="basicHttpBinding" contract="Artech.WCFService.Contract.IGeneralCalculator">
                
</endpoint>
                
<endpoint address="" binding="netTcpBinding" contract="Artech.WCFService.Contract.IGeneralCalculator" />
                
<host>
                    
<baseAddresses>
                        
<add baseAddress="http://localhost:8888/generalcalculator" />
                        
<add baseAddress="net.tcp://localhost:9999/generalCalculator" />
                    
</baseAddresses>
                
</host>
            
</service>
        
</services>
    
</system.serviceModel>
</configuration>

7. IIS-Host Configuration:

<?xml version="1.0"?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
  
<system.serviceModel>
    
<behaviors>
      
<serviceBehaviors>
        
<behavior name="calculatorServiceBehavior">
          
<serviceMetadata httpGetEnabled ="true"></serviceMetadata>
        
</behavior>
      
</serviceBehaviors>
    
</behaviors>

    
<services>
      
<service name="Artech.WCFService.Service.GeneralCalculatorService" behaviorConfiguration="calculatorServiceBehavior">
        
<endpoint binding="basicHttpBinding" contract="Artech.WCFService.Contract.IGeneralCalculator"></endpoint>
      
</service>
    
</services>
  
</system.serviceModel>
  
    
<system.web>
        
<compilation debug="true">
            
<assemblies>
                
<add assembly="System.Security, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
                
<add assembly="Microsoft.Transactions.Bridge, Version=3.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
                
<add assembly="SMDiagnostics, Version=3.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
                
<add assembly="System.IdentityModel.Selectors, Version=3.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
                
<add assembly="System.DirectoryServices, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
                
<add assembly="System.Web.RegularExpressions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
                
<add assembly="System.Transactions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
                
<add assembly="System.Messaging, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
                
<add assembly="System.ServiceProcess, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/></assemblies></compilation>
    
</system.web>
</configuration>

8. Client configuration: Artech.WCFService.Client/App.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  
<system.serviceModel>
    
<client>
    
<endpoint address="http://localhost:8888/generalCalculator" binding="basicHttpBinding" contract="Artech.WCFService.Contract.IGeneralCalculator" name="selfHostEndpoint_http"/>
       
<endpoint address="net.tcp://localhost:9999/generalCalculator" binding="netTcpBinding" contract="Artech.WCFService.Contract.IGeneralCalculator" name="selfHostEndpoint_tcp"/>
       
<endpoint address="http://localhost/wcfservice/GeneralCalculatorService.svc" binding="basicHttpBinding" contract="Artech.WCFService.Contract.IGeneralCalculator" name="iisHostEndpoint"/>
    
</client>
  
</system.serviceModel>
 
</configuration>

如何在Application中定义Endpoint

对于Self-Host的Service,绝大部分的Endpoint相关的信息都具有两种定义方式——Managed Code 和Configuration。而对于把Service Host到IIS中的情况, Endpoint的信息一般虚拟根目录下的Web.Config中定义。一般的我们我们不推荐使用代码的方式Host和调用Service,这主要是基于以下的理由。首先我们开发的环境往往与部署的环境不尽相同,才用configuration的方式是的我们可以在部署的时候通过修改配置文件以适应新的需要。其次,对于不要出现的新的需要,比如对于一个原来只供Internet内部使用的Service,我们一般会定义一个基于TCP的Endpoint,现在出现来自于Internet的潜在用户,我们只需要通过修改Config文件的方式为这个Service添加一个新的基于Http的Endpoint就可以了。 把Endpoint的信息写在config文件中的优势在于,修改config文件的内容是不需要重新编译和重新部署的。相应的定义方式清参照以上的Sample。

下面我们来看看在host 一个Service的时候,置于配置文件的信息是如何起作用的。在上面的例子中我们通过下面一段代码Host一个Serivice(对应得Service Type是GeneralCalculatorService)。

using (ServiceHost calculatorSerivceHost = new ServiceHost(typeof(GeneralCalculatorService)))
{               
        calculatorSerivceHost.Opened 
+= delegate
         
{
              Console.WriteLine(
"Calculator Service has begun to listen  ");
          }
;
         calculatorSerivceHost.Open();
         Console.Read();
}


下面是Service相关的配置信息:

<services>
            
<service behaviorConfiguration="calculatorServieBehavior" name="Artech.WCFService.Service.GeneralCalculatorService">
                 
<endpoint address="" binding="basicHttpBinding" contract="Artech.WCFService.Contract.IGeneralCalculator">
                
</endpoint>
                
<endpoint address="" binding="netTcpBinding" contract="Artech.WCFService.Contract.IGeneralCalculator" />
                
<host>
                    
<baseAddresses>
                        
<add baseAddress="http://localhost:8888/generalcalculator" />
                        
<add baseAddress="net.tcp://localhost:9999/generalCalculator" />
                    
</baseAddresses>
                
</host>
            
</service>
</services>

首先我们创建一个ServiceHost对象calculatorSerivceHost,同时指定对用的Service Type 信息(typeof(GeneralCalculatorService))。WCF Infrastructure为在配置文件在Services Section寻找是否有相对用的service定义。在这个例子中,他会找到一个name属性为Artech.WCFService.Service.GeneralCalculatorService的Service。然后他会根据定义在Service中的Endpoint定义为calculatorSerivceHost添加相应的Endpoint。 如果有对应的Endpoint Behavior设置存在于配置文件中,这些Behavior也会设置到改Endpoint中。最后调用Open方法,calculatorSerivceHost开始监听来自Client端的请求。

Address

每一个Endpoint都必须有一个Address,Address定位和唯一标志一个Endpoint。在Managed code 中,Address由System.ServiceModel.EndpointAddress对象来表示。下面是一个Adress的结构:

  • URI:指定的Endpoint的Location。URI对于Endpoint是必须的。
  • Identity:当另一个Endpoint与此Endpoint进行消息交互时,可以获取该Identity来Authenticate正在与之进行消息交互的Endpoint是否是它所希望的。Identity对于endpoint是可选的。
  • Headers:Address可以包含一些可选的Headers, 这些header最终会加到相应的Soap Message的Header中。Header存放的多为Address相关的信息,用于进行Addressing Filter。 

Address的主要作用就是同过Uri为Service提供一个监听Address。但在某些特殊的场景中,我们可以借助Address的Headers提供一些扩展的功能。在大多数的情况下Client可以直接访问Service,换句话说,如果我们把Message 传递的路径看成是以系列连续的节点(Node)的话,Message直接从Client所在的节点(Node)传递到最终的Service的节点。但在某些情况下,考虑的实现负载平衡,安全验证等因素,我们需要在Client和最终的Service之间加入一些中间节点(Intermediaries),这些中间节点可以在Message到达最终Service Node之前作一些工作,比如为了实现负载平衡,它可以把Message Request分流到不同的节点——Routing;为了在Message达到最终Node之前,验证Client是否是一个合法的请求,他可以根据Message存储的Credential的信息验证该请求——Authentication。
这些Intermediaries操作的一般不会是Message Body的内容(大多数情况下他们已经被加密),而是Message Header内容。他们可以修改Header的内容,也可以加入一些新的Header。所以为了实现Routing,我们需要在Message加入一些Addressing相关的内容,为了实现Authentication我们需要加入Client Credential的信息, 而这些信息都放在Header中。实际上你可以把很多内容加到Header中。
我们可以通过config文件加入这些Header:

<service behaviorConfiguration="calculatorServieBehavior" name="Artech.WCFService.Service.DuplexCalculatorService">
                
<endpoint binding="wsDualHttpBinding" contract="Artech.WCFService.Contract.IDuplexCalculator">
                    
<headers>
                        
<role>admin</role>
                    
</headers>
                
</endpoint>
                
<host>
                    
<baseAddresses>
                        
<add baseAddress="http://localhost:7777/DuplexCalculator" />
                    
</baseAddresses>
                
</host>
            
</service>

<client>
      
<endpoint address="http://localhost/WCFService/SessionfulCalculatorService.svc"
        binding
="wsHttpBinding" bindingConfiguration="" contract="Artech.WCFService.Contract.ISessionfulCalculator" >
<headers>
         
<role>admin</role>
                    
</headers>
                
</endpoint>
    
</client>

Binding

WCF,顾名思义就是实现了分布式系统中各Application之间的Communication的问题。上面我们说过, Client和Service之间的通信完全有他们各自的Endpoint的担当。Address解决了寻址的问题,通过Address,Client知道在哪里可以找到它所希望的Service。但是知道了地址,只是实现的通信的第一步。

对于一个基于SOA的分布式系统来说,各Application之间的通信是通过Message Exchange来实现的。如何实现在各个Application之间 进行Message的交互,首先需要考虑的是采用怎样的Transport,是采用Http呢,还是采用TCP或是其他,比如Named Pipe、MSMQ。其次需要考虑的是Message应该采取怎样的编码,是text/XML呢,还是Binary,或是MTOM;此外,对于一个企业级的分布式应用,Security与Robustness是我们必须考虑的问题——我们应该采用Transport Level的Security(SSL)还是Message Level的Security;如何确保我们的Message的传递是可靠的(Reliable Messaging); 如何把在各application中执行的操作纳入同一个事物中(Transaction)。而这一些都是Binding需要解决的问题。所以我们可以说Binding实现了Client和Service通信的所有底层细节。

在WCF中,Binding一个Binding Element的集合,每个Binding Element解决Communication的某一个方面。所有的Binding Element大体上可以分为以下3类:

1. Transport Binding Element:实现Communication的Transport选取,每个Binding必须包含一格Transport Element。

2. Encoding Binding Element:解决传递数据的编码的问题,每个Binding必须包含一个Encoding Element,一般由Transport Binding Element来提供。

3. Protocol Binding Element:解决Security,Reliable Messaging和Transaction的问题。

下边这个表格列出了Binding中的各个层次结构。

Layer

Options

Required

Transactions

TransactionFlowBindingElement

No

Reliability

ReliableSessionBindingElement

No

Security

SecurityBindingElement

No

Encoding

Text, Binary, MTOM, Custom

Yes

Transport

TCP, Named Pipes, HTTP, HTTPS, MSMQ, Custom

Yes


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-28 13:29 Artech 阅读(15539) 评论(65)  编辑 收藏 所属分类: K. WF

评论

#1楼 2007-02-28 13:41 webabcd      

还没开始学,不过早晚要学
支持一下,收藏
  回复  引用  查看    

#2楼 2007-02-28 13:46 JesseZhao      

@webabcd
你准备学wcf
我个人比较准备学workflow
  回复  引用  查看    

#3楼[楼主] 2007-02-28 13:50 Artech      

@JesseZhao
也在学习WF,希望以后一起探讨。
  回复  引用  查看    

#4楼 2007-03-02 14:18 Frank[未注册用户]

最近也在学习WCF,在看NetFX3上发布的NetFx3TrainingKit,希望能共同交流。

  回复  引用    

#5楼 2007-06-14 10:31 妖居      

我在运行的时候,发现我无法访问到IIS-Hosting的服务。
提示The remote server returned an unexpected response: (405) Method not allowed.
那个WCFService的Project是什么类型的呢?你的上一篇博文说Web Site Project,我作了个ASP.Net Application,好像不太对吧,但是我的VS2005没有Web Site Project这个类型的Template。
  回复  引用  查看    

#6楼[楼主] 2007-06-14 11:05 Artech      

@妖居
其实只要的一般的IIS虚拟目录就可以了。
可以是ASP.NET Website,Web Service Website也可以是专门的WCF Service Website。
  回复  引用  查看    

#7楼 2007-07-24 00:00 hustnn[未注册用户]

这个程序应该怎么跑?   回复  引用    

#8楼 2007-07-24 00:06 hustnn[未注册用户]

using (ServiceHost calculatorServiceHost = new ServiceHost(typeof
(GernealCalculatorService), httpBaseAddress, tcpBaseAddress))
在跑Hosting的时候,在以上的出现了异常,如下:
This collection already contains an address with scheme http. There can be at most one address per scheme in this collection.
参数名: item
  回复  引用    

#9楼 2007-07-24 00:19 hustnn[未注册用户]

晕,重复了,不好意思啊,下次我仔细看了再问   回复  引用    

#10楼 2007-07-24 00:37 hustnn[未注册用户]

self-host已经成功,下面是iis-host问题.
我已经将http://localhost/WCFService/testCalculator/GeneralCalculatorService.svc" target="_new" rel="nofollow">http://localhost/WCFService/Calculator/GeneralCalculatorService.svc发布在了iis的网站的WCFService/testCalculator中,并且修改了client的配置文件中的地址如下,其他地方没有修改,地址如下http://localhost/WCFService/testCalculator/GeneralCalculatorService.svc
,结果运行时候http://localhost/WCFService/testCalculator/GeneralCalculatorService.svc could not be activated,
应该如何解决,谢谢了
  回复  引用    

#11楼 2007-07-24 00:41 hustnn[未注册用户]

web config是不是应该做相应修改?   回复  引用    

#12楼 2007-07-24 00:52 hustnn[未注册用户]

怪了,我在Calculator中发布的可以,
在testCalculator就不能activated
  回复  引用    

#13楼[楼主] 2007-07-24 10:37 Artech      

@hustnn
对于IIS Hosting,hosting的Configuration和一般的Configuration没有什么分别。只需要将Client端的Address换成Svc file的地址就可以了。
  回复  引用  查看    

#14楼 2007-08-24 15:38 sokoo      

host到IIS情况下,调研Add出现错误
‘响应消息的内容类型 text/html; charset=utf-8 与绑定(text/xml; charset=utf-8)的内容类型不匹配’,具体什么问题?
  回复  引用  查看    

#15楼 2007-10-23 11:44 路人丙[未注册用户]

问下兄弟门,为什么我创建的wcfservice程序没有后缀为.client,.cotract这些文件 啊,只有.svc谢谢兄弟门了,急   回复  引用    

#16楼 2007-10-23 12:45 qltouming[未注册用户]

那本来就不是什么文件后缀吧,只是作者为了方便大家理解阅读,代码层次清晰,而特意那样命名的吧   回复  引用    

#17楼[楼主] 2007-10-23 13:29 Artech      

@路人丙
qltouming说的没错,仅仅是人为创建的,为了模拟远程调用环境(Service, Client)和实现Contract的重用(Contract供Client和Service使用)。
  回复  引用  查看    

#18楼 2007-10-23 13:38 路人丙[未注册用户]

谢谢兄弟门,呵呵,明白,非学感谢好人们   回复  引用    

#19楼 2007-10-30 18:40 neal1985[未注册用户]

我看完我的WCF之旅(2)啦我要用来做毕业设计   回复  引用    

#20楼 2007-10-31 10:18 yiyanxiyin      

<services>
<service behaviorConfiguration="calculatorServieBehavior" name="Artech.WCFService.Service.GeneralCalculatorService">
<endpoint address="" binding="basicHttpBinding" contract="Artech.WCFService.Contract.IGeneralCalculator">
</endpoint>
<endpoint address="" binding="netTcpBinding" contract="Artech.WCFService.Contract.IGeneralCalculator" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8888/generalcalculator"" target="_new">http://localhost:8888/generalcalculator" />
<add baseAddress="net.tcp://localhost:9999/generalCalculator" />
</baseAddresses>
</host>
</service>
</services>

endpoint的address为空,它怎么确定address的?
  回复  引用  查看    

#21楼 2007-11-02 13:31 winnerzone      

好郁闷的bolg样式.虽然是新的2008,但是有bug文章都看不全了,希望博主修改下.看文章只能粘贴下来到word下看了.   回复  引用  查看    

#22楼[楼主] 2007-11-02 16:51 Artech      

@yiyanxiyin
使用base address!
  回复  引用  查看    

#23楼 2007-11-03 13:19 zhouxw[未注册用户]

楼主
我完全是个新手呀,我的是windows 2003的系统,用你的源代码运行怎么出现这样的错误呀,请问是为什么呀?麻烦你帮帮忙呀!

There was no endpoint listening at http://localhost/wcfservice/GeneralCalculatorService.svc that could accept the message.
  回复  引用    

#24楼 2008-01-23 17:50 Silent Void      

向楼主请教:
如果配置了EndPoint的逻辑地址(address)和物理地址(listenUri),则客户端生成的Config文件中,连接地址指向逻辑地址,这是调用ServiceMethod会抛出异常:
Additional information: There was no endpoint listening at http://...../LogicAddress that could accept the message. This is often caused by an incorrect address or SOAP action。

如果手动修改Config的配置文件,将EndPoint的Address属性配置成逻辑地址,behaviorConfiguration配置相应的物理地址,却又抛出:
Additional information: The binding specified requires that the to and via URIs must match because the Addressing Version is set to None.

请问楼主有没有遇到类似的问题?
thanks:)
  回复  引用  查看    

#25楼 2008-02-12 15:47 jillzhang      

@yiyanxiyin
endpoint address=""
中的address是相对地址,相对什么的呢?相对的是基地址,基地址是通过http://localhost:8888/generalcalculator" />来设置的,如果address="",说明endpoint的地址就是基地址
  回复  引用  查看    

#26楼 2008-02-12 15:53 jillzhang      

@Silent Void
behavior中设置的是meta地址,也就是wsdl文件路径,而不是endpoint的监听地址,所以会出现你下面说的那种情况
而你上面的情况,如果将address设置为绝对地址,那baseAddress设置将失效
http://www.cnblogs.com/jillzhang/archive/2008/01/30/1059169.html" target="_new">http://www.cnblogs.com/jillzhang/archive/2008/01/30/1059169.html
  回复  引用  查看    

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

正在学习,这个系列不错   回复  引用    

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

感谢,学习中   回复  引用    

#29楼 2008-05-07 15:42 傻样精英      

响应消息的内容类型 text/html; charset=utf-8 与绑定(text/xml; charset=utf-8)的内容类型不匹配。

是什么问题?
  回复  引用  查看    

#30楼[楼主] 2008-05-07 16:02 Artech      

@傻样精英
这个问题我也没有一个明确的答案。
貌似这个问题是这样产生的:通过IIS调用Serivce, 遇到一些异常IIS会返回一个各Html Page,WCF client获得HTML,就会报你提到的这样的问题, 因为它希望的是XML,而不是HTML。
如果你操看Event Viewer的话,会发现这样的Log:aspnet_wp.exe (PID: 3672) stopped unexpectedly.
  回复  引用  查看    

#31楼 2008-05-07 17:49 傻样精英      

谢谢,你的意思是有可能我的serivce写的有问题报了异常了?
有可能哦,我用silverlight调用报错如下:
错误信息:
“System.ServiceModel.CommunicationException”类型的异常在 System.ServiceModel.dll 中发生,但未在用户代码中进行处理

其他信息: Operation is not valid due to the current state of the object.
  回复  引用  查看    

#32楼 2008-05-07 17:53 傻样精英      

我的邮箱:shanshengsheng@gmail.com

你给我发个email,我把我做的程序发给你帮看看吧?看了三天了都没看出问题所在。太郁闷了
  回复  引用  查看    

#33楼 2008-09-02 00:21 edrp.cn      

@Artech

我的理解是
Address:指WCF提供服务的地址
Binding:使用什么通信协议和WCF的服务通信
Contract:是WCF提供什么样的功能
不知是否正确?
Behavior我还是不能完全理解,请LZ通俗的再加以叙述,谢谢
  回复  引用  查看    

#34楼[楼主] 2008-09-02 09:15 Artech      

@edrp.cn
Behavior可以理解为Client向Server端发送请求的行为,以及Server端接受、处理请求的行为。
  回复  引用  查看    

#35楼 2008-09-05 14:56 AlexLiu      

对于新手来看,还是注释或者讲解少了点。看起来多少有点吃力。   回复  引用  查看    

#36楼 2008-10-03 15:25 从天而降      

--引用--------------------------------------------------
傻样精英: 响应消息的内容类型 text/html; charset=utf-8 与绑定(text/xml; charset=utf-8)的内容类型不匹配。
<br>
<br>是什么问题?
--------------------------------------------------------
关于这个问题,我有一个参考答案。这类问题一般是由于IIS内部错误所致,通过网页查看时往往会得到HTTP 500的错误提示,此时打开系统事件查看器,可能会看到一个警告:服务器无法加载应用程序 '/LM/W3SVC/1/ROOT'。错误是 '没有注册类别'。有关此消息的详细信息......。

如此一般解决办法如下:
1. 在“开始”-“运行”中执行命令:msdtc -resetlog
2. 重启电脑,检查IIS是否可正常使用。如不行,则继续以下步骤。
3. 在CMD下执行以下命令:
(1). cd %windir%system32inetsrv
(2). rundll32 wamreg.dll, CreateIISPackage
(3). regsvr32 asptxn.dll /u
(4). regsvr32 asptxn.dll
(5). IISReset (或者重启机器)


感谢博主的伟大!!!
  回复  引用  查看    

#37楼[楼主] 2008-10-04 08:35 Artech      

@从天而降
谢谢提供解决方案,IIS Host 的情况下容易出现这样第一个ProtocolException
  回复  引用  查看    

#38楼 2008-10-08 11:37 傻样精英      

谢谢上面2位

但是我机器里面好像就没有asptxn.dll,呵呵
  回复  引用  查看    

#39楼 2008-11-08 23:24 排骨面的马甲[未注册用户]

好文!! 刚拜读完您的企业库的文章,现在准备开始学WCF。

btw:顺便问下,楼主的表是什么牌子的? 很拉风啊~~~
  回复  引用    

#40楼[楼主] 2008-11-10 09:38 Artech      

@排骨面的马甲
hehe,我的表几十块钱一支而已!
  回复  引用  查看    

#41楼 2008-11-13 16:42 sunrenpeng      

如何让 scoket 客户端(比如c语言写的) 与wcf服务端通讯(C#写)   回复  引用  查看    

#42楼[楼主] 2008-11-14 10:15 Artech      

@sunrenpeng
Socket和WCF, 它们应用的场景,解决的问题完全不相同, 所以之间的互操作没有什么意义。你的问题相当于说 scoket 客户端输入调用Web Service。
  回复  引用  查看    

#43楼 2008-11-14 10:55 sunrenpeng      

在进行大量数据传输的时候,速度会很快的。目的是传说大量数据。   回复  引用  查看    

#44楼 2008-11-14 10:58 sunrenpeng      

如果要实现scoket 客户端(比如c语言写的) 与wcf服务端通讯(C#写)通讯,传输大量数据,能给出实现的思路吗   回复  引用  查看    

#45楼[楼主] 2008-11-14 12:21 Artech      

@sunrenpeng
如果你仅仅是单纯的进行数据传输,既然客户端是Socket,我觉得直接使用Socket进行数据传输就可以了为何要用WCF。至于WCF的大数据的问题,可以采用MTOM编码,活着采用stream的方式。
  回复  引用  查看    

#46楼 2009-03-03 17:21 chgBlog      

妙文,赞一个!   回复  引用  查看    

#47楼[楼主] 2009-03-09 08:46 Artech      

--引用--------------------------------------------------
chgBlog: 妙文,赞一个!
--------------------------------------------------------
thanks!!
  回复  引用  查看    

#48楼 2009-05-07 17:29 vivounicorn      

好文章! 好看 比美女好看多了 哈哈哈   回复  引用  查看    

#49楼[楼主] 2009-05-13 12:44 Artech      

--引用--------------------------------------------------
vivounicorn: 好文章! 好看 比美女好看多了 哈哈哈
--------------------------------------------------------
美女,还是不能少的:)
  回复  引用  查看    

#50楼 2009-06-09 14:34 咸鱼翻身      

你好
示例代码结构很清晰,
看了收获很大,不过有个疑问
class GeneralCalculatorClient:ClientBase<IGeneralCalculator>,IGeneralCalculator
{
public GeneralCalculatorClient()
: base()
{ }

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

public GeneralCalculatorClient(Binding binding, EndpointAddress address)
: base(binding, address)
{ }

#region IGeneralCalculator Members

public double Add(double x, double y)
{
return this.Channel.Add(x, y);
}

#endregion
}

上段代码如何生成
还是手工编写吗
如果很多这样的服务应该处理
是不是还有工具生成这样客户端代理
  回复  引用  查看    

#51楼 2009-06-09 14:49 咸鱼翻身      

IGeneralCalculator Proxy = new ChannelFactory<IGeneralCalculator>("selfHostEndpoint_http").CreateChannel();
通过这个似乎也能消费服务端提供的服务。
无论是通过生成代理类或者是上面方式都需要引用IGeneralCalculator定义
如果其他应用程序要使用消费这样的服务,应该怎么去使用了?
谢谢
  回复  引用  查看    

#52楼[楼主] 2009-06-10 08:05 Artech      

--引用--------------------------------------------------
咸鱼翻身: IGeneralCalculator Proxy = new ChannelFactory&lt;IGeneralCalculator&gt;(&quot;selfHostEndpoint_http&quot;).CreateChannel();
通过这个似乎也能消费服务端提供的服务。
无论是通过生成代理类或者是上面方式都需要引用IGeneralCalculator定义
如果其他应用程序要使用消费这样的服务,应该怎么去使用了?
谢谢
--------------------------------------------------------
通过SvcUtil.exe这样的Code Generator Tool导入Metadata,在本地生成服务代理相关的类型和配置。

“添加服务引用”即采用这样的机制!
  回复  引用  查看    

#53楼[楼主] 2009-06-10 08:07 Artech      

--引用--------------------------------------------------
咸鱼翻身: 你好
示例代码结构很清晰,
看了收获很大,不过有个疑问
class GeneralCalculatorClient:ClientBase&lt;IGeneralCalculator&gt;,IGeneralCalculator
{
public GeneralCalculatorClient()
: base()
{ }

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

public GeneralCalculatorClient(Binding binding, EndpointAddress address)
: base(binding, address)
{ }

#region IGeneralCalculator Members

public double Add(double x, double y)
{
return this.Channel.Add(x, y);
}

#endregion
}

上段代码如何生成
还是手工编写吗
如果很多这样的服务应该处理
是不是还有工具生成这样客户端代理
--------------------------------------------------------
这段代码是手工编写,你可以直接通过SvcUtil.exe,或者借助VS的添加服务引用的方式生成相关代码和配置!
  回复  引用  查看    

#54楼 2009-06-10 08:28 咸鱼翻身      

多谢了高手了   回复  引用  查看    

#55楼 2009-06-10 15:03 太阳仔[未注册用户]

<client>
<endpoint address="http://localhost/WCFService/SessionfulCalculatorService.svc"
binding="wsHttpBinding" bindingConfiguration="" contract="Artech.WCFService.Contract.ISessionfulCalculator" >
<headers>
<role>admin</role>
</headers>
</endpoint>
</client>

Client可以不用Config 来获取信息吗?因为不想建一个app.config。用代码来获取。可以实现吗?
  回复  引用    

#56楼[楼主] 2009-06-10 21:50 Artech      

--引用--------------------------------------------------
太阳仔: &lt;client&gt;
&lt;endpoint address=&quot;<a href="http://localhost/WCFService/SessionfulCalculatorService.svc&quot;" target="_new" rel="nofollow">http://localhost/WCFService/SessionfulCalculatorService.svc&quot;</a>
binding=&quot;wsHttpBinding&quot; bindingConfiguration=&quot;&quot; contract=&quot;Artech.WCFService.Contract.ISessionfulCalculator&quot; &gt;
&lt;headers&gt;
&lt;role&gt;admin&lt;/role&gt;
&lt;/headers&gt;
&lt;/endpoint&gt;
&lt;/client&gt;

Client可以不用Config 来获取信息吗?因为不想建一个app.config。用代码来获取。可以实现吗?
--------------------------------------------------------
实际上,所有通过配置提供的内容都可以通过编码的方式指定!
  回复  引用  查看    

#57楼 2009-06-12 14:52 蓝蓝的月亮      

楼主你好!
为什么你给出的DEMO,我自己把host修改了一下,在WPF和WinForm中就不行,但是在控制台中一点问题也没有,是怎么回事,希望解答一下。
谢谢
  回复  引用  查看    

#58楼 2009-06-12 15:07 蓝蓝的月亮      

代码如下:
private void btBegin_Click(object sender, RoutedEventArgs e)
{
HostCalculatorSerivceViaConfiguration();
}
static void HostCalculatorSerivceViaConfiguration()
{
using (ServiceHost calculatorSerivceHost = new ServiceHost(typeof(GeneralCalculatorService)))
{
calculatorSerivceHost.Opened += delegate
{
...
};

calculatorSerivceHost.Open();
}
}
  回复  引用  查看    

#59楼[楼主] 2009-06-12 15:46 Artech      

using (ServiceHost calculatorSerivceHost = new ServiceHost(typeof(GeneralCalculatorService)))

ServiceHost is DISPOSED!!!
  回复  引用  查看    

#60楼 2009-06-12 17:10 太阳仔[未注册用户]

@Artech
--引用--------------------------------------------------
Artech: --引用--------------------------------------------------
太阳仔: &amp;lt;client&amp;gt;
&amp;lt;endpoint address=&amp;quot;&lt;a href=&quot;http://localhost/WCFService/SessionfulCalculatorService.svc&amp;quot;&quot; target=&quot;_new&quot; rel=&quot;nofollow&quot;&gt;http://localhost/WCFService/SessionfulCalculatorService.svc&amp;quot;&lt;/a&gt;
binding=&amp;quot;wsHttpBinding&amp;quot; bindingConfiguration=&amp;quot;&amp;quot; contract=&amp;quot;Artech.WCFService.Contract.ISessionfulCalculator&amp;quot; &amp;gt;
&amp;lt;headers&amp;gt;
&amp;lt;role&amp;gt;admin&amp;lt;/role&amp;gt;
&amp;lt;/headers&amp;gt;
&amp;lt;/endpoint&amp;gt;
&amp;lt;/client&amp;gt;

Client可以不用Config 来获取信息吗?因为不想建一个app.config。用代码来获取。可以实现吗?
--------------------------------------------------------
实际上,所有通过配置提供的内容都可以通过编码的方式指定!
--------------------------------------------------------
有没编码的例子啊?
  回复  引用    

#61楼 2009-06-12 22:54 蓝蓝的月亮      

谢谢,原来是作用域的原因。
以前从来没有意识到。
  回复  引用  查看    




发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 659331




相关文章:

相关链接: