我目前正在使用WebServiceHost在Windows服务(而非IIS)中运行一些WCF REST服务。我为每个服务定义了单独的接口和类,但是在理解如何将WebServiceHostServiceEndpointServiceContracts一起使用以创建自托管解决方案时遇到了一些问题。

我目前设置的方式是,我为每个实现服务的类创建一个新的WebServiceHost,并使用该类的名称作为URI的一部分,然后在接口中定义URI的其余部分。

[ServiceContract]
public interface IEventsService
{
    [System.ServiceModel.OperationContract]
    [System.ServiceModel.Web.WebGet(UriTemplate = "EventType", ResponseFormat=WebMessageFormat.Json)]
    List<EventType> GetEventTypes();

    [System.ServiceModel.OperationContract]
    [System.ServiceModel.Web.WebGet(UriTemplate = "Event")]
    System.IO.Stream GetEventsAsStream();
 }

public class EventsService: IEventsService
{
     public List<EventType> GetEventTypes() { //code in here }
     public System.IO.Stream GetEventsAsStream() { // code in here }
}


创建服务的代码如下所示:

Type t = typeof(EventService);
Type interface = typeof(IEventService);

Uri newUri = new Uri(baseUri, "Events");
WebServicesHost host = new WebServiceHost(t, newUri);
Binding binding = New WebHttpBinding();
ServiceEndpoint ep = host.AddServiceEndpoint(interface, binding, newUri);


这很好用,并且每个服务的服务端点都在适当的URL上创建。

http://XXX.YYY.ZZZ:portnum/Events/EventType
http://XXX.YYY.ZZZ:portnum/Events/Event

然后,我重复另一个服务接口和服务类。我想在网址中删除Events,但是如果我这样做并使用相同的基本URL创建多个WebServiceHosts,则会收到错误消息:

The ChannelDispatcher at 'http://localhost:8085/' with contract(s) '"IOtherService"' is unable to open its IChannelListener

具有以下内部异常:

"A registration already exists for URI 'http://localhost:8085/'."

我试图了解WebServiceHostServiceEndpointServiceContract如何共同创建ChannelListener。

每个实现服务的类是否都需要一个单独的WebServiceHost?我看不到用单个WebServiceHost注册多种类型的方法

其次,我将接口传递给AddServceEndpoint方法,并假定该方法检查所有OperationContract成员的对象并将其添加,问题是WebServiceHost如何知道哪个类应映射到哪个接口。

我想举一个创建WCF自托管服务的示例,该服务运行多个服务,同时使接口和实现类保持分离。

最佳答案

在我看来,您遇到的问题是您试图在同一服务URI上注册多个服务。正如您已经注意到的那样,这将不起作用,每个服务必须具有唯一的端点。

唯一依据


知识产权

端口号
完整网址


例子

http://someserver/foo  -> IFoo Service
http://someserver/bar  -> IBar Service

http://somedomain  -> IFoo Service
http://someotherdomain  -> IBar Service

http://somedomain:1  -> IFoo Service
http://somedomain:2 -> IBar Service


你明白了。

因此,要直接解决您的问题,如果您希望将多个服务放在您网站的根URL中,则必须将它们放在不同的端口上。因此,您可以将代码修改为类似

public class PortNumberAttribute : Attribute
{
    public int PortNumber { get; set; }
    public PortNumberAttribute(int port)
    {
        PortNumber = port;
    }
}

[PortNumber(8085)]
public interface IEventsService
{
    //service methods etc
}


string baseUri = "http://foo.com:{0}";
Type iface = typeof(IEventsService);
PortNumberAttribute pNumber = (PortNumberAttribute)iface.GetCustomAttribute(typeof(PortNumberAttribute));
Uri newUri = new Uri(string.Format(baseUri, pNumber.PortNumber));

//create host and all that

10-04 16:05