我有一个带有自定义绑定的WCF服务,托管在IIS(开发中的IIS Express)中,具有以下服务合同:
[ServiceContract]
public interface IServer
{
[OperationContract]
StreamCollection GetStreams(Guid poolKey);
[OperationContract]
PoolCollection GetPools();
[OperationContract]
StreamEntity GetStream(Guid poolKey, string localIndex);
}
它工作正常(来自客户端,我也可以看到它在WCFTestClient中发现了元数据) 我必须将其功能公开为REST,因此我创建了一个新合同,如下所示
[ServiceContract]
public interface IRestServer
{
[OperationContract(Name="GetStreamsREST")]
[WebGet(UriTemplate = "pool/{poolKey}/streams")]
StreamCollection GetStreams(string poolKey);
[OperationContract(Name = "GetPoolsREST")]
[WebGet(UriTemplate = "pools")]
PoolCollection GetPools();
[OperationContract(Name = "GetStreamREST")]
[WebGet(UriTemplate = "pool/{poolKey}/stream/{localIndex}")]
StreamEntity GetStream(string poolKey, string localIndex);
}
我在同一服务类中实现了两个接口。 web.config文件是
<behaviors>
<endpointBehaviors>
<behavior name="webHttp">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<customBinding>
<binding name="CustomBinding">
<binaryMessageEncoding />
<httpTransport maxReceivedMessageSize="655360" />
</binding>
</customBinding>
</bindings>
<services>
<service behaviorConfiguration="ServiceBehavior" name="MyServ.Server.Server">
<endpoint address="" binding="customBinding" bindingConfiguration="CustomBinding" contract="MyServ.Server.IServer" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<endpoint address="rest" behaviorConfiguration="webHttp" binding="webHttpBinding" contract="MyServ.Server.IRestServer" />
</service>
</services>
然而,当我浏览使用rest访问服务时,有像
这样的URLhttp://localhost:<myport>/Service.svc/pools
http://localhost:<myport>/Service.svc/pool/somekey/streams
http://localhost:<myport>/Service.svc/pool/somekey/streams
我收到错误404.
我在某些方法中设置了一个断点,并将调试器附加到IIS进程,但似乎没有任何调用。
如果我使用WCFTestClient检查服务元数据,它只会看到IService,但不会看到IRestService。这是正常的吗? 编辑:是的,似乎是(check this)
感谢您的任何建议。
答案 0 :(得分:2)
REST端点不会以WCFTestClient可以使用的方式公开元数据,这解释了为什么您无法访问它。您浏览的地址不正确,因为您将REST端点的端点地址指定为“rest”,您需要以类似
的方式访问它们http://localhost:port/Service.svc/rest/pool/myPoolKey/streams
http://localhost:port/Service.svc/rest/pools
http://localhost:port/Service.svc/rest/myPoolKey/stream/1
另一件事:Name
属性中的[OperationContract]
属性对于REST端点无关紧要,因此您可以删除它(尽管如此,它并没有伤害它)。此外,如果您使用的是.NET 4.0,则根本不需要[OperationContract]
属性,因为您已经拥有[WebGet]
,因此您的界面可以定义为
[ServiceContract]
public interface IRestServer
{
[WebGet(UriTemplate = "pool/{poolKey}/streams")]
StreamCollection GetStreams(string poolKey);
[WebGet(UriTemplate = "pools")]
PoolCollection GetPools();
[WebGet(UriTemplate = "pool/{poolKey}/stream/{localIndex}")]
StreamEntity GetStream(string poolKey, string localIndex);
}
答案 1 :(得分:1)
您是否可以发布有关如何调用WCF服务的代码?前几天我遇到了类似的问题,客户端应用程序使用HTTP POST而不是HTTP GET调用页面,因此出现404错误。
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped, ResponseFormat = WebMessageFormat.Json, UriTemplate = "/GuessWhat")]
vs
[WebGet(UriTemplate = "/GuessWhat/{variable}", ResponseFormat = WebMessageFormat.Json)]
我不确定您的服务是否包含此项,但请确保实施服务合同的服务具有此属性。
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
答案 2 :(得分:1)
感谢大家的所有建议。 但是,我终于解决了这个问题。
问题是我不知道问题是什么,但我决定采取一种不同的,更“干净”的方式。
所以我做的是创建一个不同的服务SVC文件RestServer,我实现了REST方法
我修改了web config中的设置以获得两个不同的服务,一个用于原始服务(纯WCF),另一个用于REST服务,如下所示
<service name="MyServ.Server.RestServer" >
<endpoint address="" name="RESTEndpoint" behaviorConfiguration="webHttp" binding="webHttpBinding" contract="MyServ.Server.IRestServer" />
</service>
这就是诀窍。
实际上,我应该从一开始就使用这种方法,以遵守单一的责任原则......