通过 HTTP 访问 WCF 服务
Posted
技术标签:
【中文标题】通过 HTTP 访问 WCF 服务【英文标题】:Accessing WCF service via HTTP 【发布时间】:2017-05-10 08:23:49 【问题描述】:我在 Visual Studio 中编写了一个非常简单的 WCF 项目:
IBookStore:
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
namespace BookStore
[ServiceContract]
public interface IBookStore
[OperationContract]
[WebGet]
List<Book> GetBooksList();
[OperationContract]
[WebGet(UriTemplate = "GetBook/id")] // The value of UriTemplate defines the name that the
// client should use to turn to the function
Book GetBookById(int id);
[OperationContract]
[WebInvoke(UriTemplate = "AddBook/name", Method = "PUT")]
void AddBook(string name);
[OperationContract]
[WebInvoke(UriTemplate = "UpdateBook/id/name", Method = "POST")]
void UpdateBook(int id, string name);
[OperationContract]
[WebInvoke(UriTemplate = "DeleteBook/id", Method = "DELETE")]
void DeleteBook(int id);
[DataContract]
public class Book
int id;
string name;
[DataMember]
public int ID
get return id;
set id = value;
[DataMember]
public string Name
get return name;
set name = value;
BookStoreImpl:
using System.Collections.Generic;
using System.ServiceModel;
using System.ServiceModel.Activation;
namespace BookStore
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class BookStoreImpl : IBookStore
public void AddBook(string name)
using (var db = new BookStoreContext())
Book book = new BookStore.Book Name = name ;
db.Books.Add(book);
db.SaveChanges();
public void DeleteBook(int id)
try
using (var db = new BookStoreContext())
Book book = db.Books.Find(id);
db.Books.Remove(book);
db.SaveChanges();
catch
throw new FaultException("Something went wrong");
public Book GetBookById(int id)
using (var db = new BookStoreContext())
return db.Books.Find(id);
public List<Book> GetBooksList()
List<Book> allBooks = new List<Book>();
try
using (var db = new BookStoreContext())
IEnumerator<Book> booksEnum = db.Books.GetEnumerator();
booksEnum.Reset();
while (booksEnum.MoveNext())
allBooks.Add(booksEnum.Current);
catch
throw new FaultException("Something went wrong");
return allBooks;
public void UpdateBook(int id, string name)
try
using (var db = new BookStoreContext())
Book book = db.Books.Find(id);
book.Name = name;
db.SaveChanges();
catch
throw new FaultException("Something went wrong");
我的 WebConfig 文件是:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5.2" />
<httpRuntime targetFramework="4.5.2" />
<httpModules>
<add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" />
</httpModules>
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="WebBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="MyServiceBehavior" name="BookStore.BookStoreImpl">
<endpoint address="http://localhost:8080/bookservice/" binding="wsHttpBinding" contract="BookStore.IBookStore" />
<endpoint address="" behaviorConfiguration="WebBehavior"
binding="webHttpBinding"
contract="BookStore.IBookStore">
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
</system.serviceModel>
<!--
<system.serviceModel>
<services>
<service name="BookStore.BookStoreImpl">
<endpoint address="http://localhost:8080/bookservice"
behaviorConfiguration="restfulBehavior" binding="webHttpBinding"
bindingConfiguration="" contract="BookStore.IBookStore"
/>
<host>
<baseAddresses>
<add baseAddress="http://localhost:8080/bookservice" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="restfulBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
-->
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<remove name="ApplicationInsightsWebTracking" />
<add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" preCondition="managedHandler" />
</modules>
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true" />
<validation validateIntegratedModeConfiguration="false" />
</system.webServer>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="mssqllocaldb" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
</configuration>
我还创建了数据库,使用 .mdf 文件将其附加到项目中,编译并运行项目,运行项目后我可以在屏幕右上角看到计时器正在运行。然后我打开我的浏览器,在地址框中输入:http://localhost:8080/bookservice/GetBooksList 并按回车,我得到一个错误页面。看起来我的请求一开始就没有到达服务器。谁能帮我理解为什么?
这是错误:
编辑:我注意到如果我在某处设置断点并运行,我会在弹出的“WCF 测试客户端”窗口中看到以下错误: “错误:无法从http://localhost:59250/BookStoreImpl.svc获取元数据如果这是您有权访问的Windows(R) Communication Foundation服务,请检查您是否已在指定地址启用元数据发布。有关启用元数据发布的帮助,请参阅http://go.microsoft.com/fwlink/?LinkId=65455.WS-Metadata 处的 MSDN 文档 Exchange 错误 URI:http://localhost:59250/BookStoreImpl.svc 元数据包含无法解析的引用:“http://localhost:59250/BookStoreImpl.svc”。无法激活请求的服务“http://localhost:59250/BookStoreImpl.svc”。有关更多信息,请参阅服务器的诊断跟踪日志information.HTTP GET 错误 URI:http://localhost:59250/BookStoreImpl.svc 下载“http://localhost:59250/BookStoreImpl.svc”时出错。请求失败并显示错误消息:-- 没有协议绑定与给定地址“http://localhost:8080/bookservice/”匹配。协议绑定在IIS 或 WAS 配置中的站点级别 body font-family:"Verdana";font-weight:normal;font-size: .7em;color:black; p font-family:"Verdana";font-weight:正常;颜色:黑色;上边距: -5px b font-family:"Verdana";font-weight:bold;color:black;margin-top:-5px H1 font-family:"Verdana";font-weight:normal;font-size: 18pt;color:red H2 font-family:"Verdana";font-weight:normal;font-size:14pt;color:maroon pre font-family:"Consolas","Lucida Console",Monospace;font -size:11pt;margin:0;padding:0.5em;line-height:14pt .marker font-weight:粗体;颜色:黑色;文本装饰:无; .version 颜色:灰色; .error margin-bottom:10px; .expandable 文本装饰:下划线;字体粗细:粗体;颜色:海军蓝;光标:手; @media screen and (max-width: 639px) pre width: 440px;溢出:自动;空白:预包装; word-wrap:断词; @media screen and (max-width: 479px) pre width: 280px;
“/”应用程序中的服务器错误。
没有与给定地址“http://localhost:8080/bookservice/”匹配的协议绑定。协议绑定在 IIS 或 WAS 配置中的站点级别进行配置。
说明:在执行当前 Web 请求期间发生未处理的异常。请查看堆栈跟踪以获取有关错误及其源自代码的位置的更多信息。 异常详细信息:System.InvalidOperationException:没有协议绑定与给定地址“http://localhost:8080/bookservice/”匹配。协议绑定在 IIS 或 WAS 配置中的站点级别进行配置。源错误:An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
堆栈跟踪: [InvalidOperationException: No protocol binding matches the given address '@987654333@'. Protocol bindings are configured at the Site level in IIS or WAS configuration.] System.ServiceModel.Activation.HostedAspNetEnvironment.GetBaseUri(String transportScheme, Uri listenUri) +109963 System.ServiceModel.Channels.TransportChannelListener.OnOpening() +13058405 System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +265 System.ServiceModel.Channels.DatagramChannelDemuxer2.OnOuterListenerOpen(ChannelDemuxerFilter filter, IChannelListener listener, TimeSpan timeout) +445 System.ServiceModel.Channels.SingletonChannelListener
3.OnOpen(TimeSpan timeout) +78 System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +308 System.ServiceModel.Dispatcher.ChannelDispatcher.OnOpen(TimeSpan timeout) +61[InvalidOperationException: The ChannelDispatcher at '@987654334@' with contract(s) '"SecurityNegotiationContract"' is unable to open its IChannelListener.] System.ServiceModel.Dispatcher.ChannelDispatcher.OnOpen(TimeSpan timeout) +134 System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +308 System.ServiceModel.ServiceHostBase.OnOpen(TimeSpan timeout) +136 System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +308 System.ServiceModel.Security.NegotiationTokenAuthenticator1.OnOpen(TimeSpan timeout) +137 System.ServiceModel.Security.WrapperSecurityCommunicationObject.OnOpen(TimeSpan timeout) +21 System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +308 System.ServiceModel.Security.CommunicationObjectSecurityTokenAuthenticator.Open(TimeSpan timeout) +23 System.ServiceModel.Security.SymmetricSecurityProtocolFactory.OnOpen(TimeSpan timeout) +513 System.ServiceModel.Security.WrapperSecurityCommunicationObject.OnOpen(TimeSpan timeout) +21 System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +308 System.ServiceModel.Security.SecurityListenerSettingsLifetimeManager.Open(TimeSpan timeout) +86 System.ServiceModel.Channels.SecurityChannelListener
1.OnOpen(TimeSpan timeout) +240 System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +308 System.ServiceModel.Dispatcher.ChannelDispatcher.OnOpen(TimeSpan timeout) +61[InvalidOperationException: The ChannelDispatcher at '@987654335@' with contract(s) '"IssueAndRenewSession"' is unable to open its IChannelListener.] System.ServiceModel.Dispatcher.ChannelDispatcher.OnOpen(TimeSpan timeout) +134 System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +308 System.ServiceModel.ServiceHostBase.OnOpen(TimeSpan timeout) +136 System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +308 System.ServiceModel.Security.SecuritySessionSecurityTokenAuthenticator.OnOpen(TimeSpan timeout) +129 System.ServiceModel.Security.WrapperSecurityCommunicationObject.OnOpen(TimeSpan timeout) +21 System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +308 System.ServiceModel.Security.CommunicationObjectSecurityTokenAuthenticator.Open(TimeSpan timeout) +23 System.ServiceModel.Security.SecuritySessionServerSettings.OnOpen(TimeSpan timeout) +759 System.ServiceModel.Security.WrapperSecurityCommunicationObject.OnOpen(TimeSpan timeout) +21 System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +308 System.ServiceModel.Security.SecurityListenerSettingsLifetimeManager.Open(TimeSpan timeout) +130 System.ServiceModel.Channels.SecurityChannelListener1.OnOpen(TimeSpan timeout) +240 System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +308 System.ServiceModel.Dispatcher.ChannelDispatcher.OnOpen(TimeSpan timeout) +61[InvalidOperationException: The ChannelDispatcher at 'http://localhost:8080/bookservice/' with contract(s) '"IBookStore"' is unable to open its IChannelListener.] System.ServiceModel.Dispatcher.ChannelDispatcher.OnOpen(TimeSpan timeout) +134 System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +308 System.ServiceModel.ServiceHostBase.OnOpen(TimeSpan timeout) +136 System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +308 System.ServiceModel.HostingManager.ActivateService(ServiceActivationInfo serviceActivationInfo, EventTraceActivity eventTraceActivity) +110 System.ServiceModel.HostingManager.EnsureServiceAvailable(String normalizedVirtualPath, EventTraceActivity eventTraceActivity) +641[ServiceActivationException: The service '/BookStoreImpl.svc' cannot be activated due to an exception during compilation. The exception message is: The ChannelDispatcher at 'http://localhost:8080/bookservice/' with contract(s) '"IBookStore"' is unable to open its IChannelListener..] System.Runtime.AsyncResult.End(IAsyncResult result) +481507 System.ServiceModel.Activation.HostedHttpRequestAsyncResult.End(IAsyncResult result) +174 System.ServiceModel.Activation.ServiceHttpModule.EndProcessRequest(IAsyncResult ar) +351314 System.Web.AsyncEventExecutionStep.OnAsyncEventCompletion(IAsyncResult ar) +9791593</pre></code> </td> </tr> </table> <br> <hr width=100% size=1 color=silver> <b>Version Information:</b>ÿMicrosoft .NET Framework Version:4.0.30319; ASP.NET Version:4.6.1586.0 </font> </body></html><!-- [InvalidOperationException]: No protocol binding matches the given address 'http://localhost:8080/bookservice/'. Protocol bindings are configured at the Site level in IIS or WAS configuration. at System.ServiceModel.Activation.HostedAspNetEnvironment.GetBaseUri(String transportScheme, Uri listenUri) at System.ServiceModel.Channels.TransportChannelListener.OnOpening() at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) at System.ServiceModel.Channels.DatagramChannelDemuxer
2.OnOuterListenerOpen(ChannelDemuxerFilter filter, IChannelListener listener, TimeSpan timeout) at System.ServiceModel.Channels.SingletonChannelListener3.OnOpen(TimeSpan timeout) at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) at System.ServiceModel.Dispatcher.ChannelDispatcher.OnOpen(TimeSpan timeout)[InvalidOperationException]: The ChannelDispatcher at 'http://localhost:8080/bookservice/' with contract(s) '"SecurityNegotiationContract"' is unable to open its IChannelListener. at System.ServiceModel.Dispatcher.ChannelDispatcher.OnOpen(TimeSpan timeout) at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) at System.ServiceModel.ServiceHostBase.OnOpen(TimeSpan timeout) at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) at System.ServiceModel.Security.NegotiationTokenAuthenticator
1.OnOpen(TimeSpan timeout) at System.ServiceModel.Security.WrapperSecurityCommunicationObject.OnOpen(TimeSpan timeout) at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) at System.ServiceModel.Security.CommunicationObjectSecurityTokenAuthenticator.Open(TimeSpan timeout) at System.ServiceModel.Security.SymmetricSecurityProtocolFactory.OnOpen(TimeSpan timeout) at System.ServiceModel.Security.WrapperSecurityCommunicationObject.OnOpen(TimeSpan timeout) at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) at System.ServiceModel.Security.SecurityListenerSettingsLifetimeManager.Open(TimeSpan timeout) at System.ServiceModel.Channels.SecurityChannelListener1.OnOpen(TimeSpan timeout) at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) at System.ServiceModel.Dispatcher.ChannelDispatcher.OnOpen(TimeSpan timeout)[InvalidOperationException]: The ChannelDispatcher at 'http://localhost:8080/bookservice/' with contract(s) '"IssueAndRenewSession"' is unable to open its IChannelListener. at System.ServiceModel.Dispatcher.ChannelDispatcher.OnOpen(TimeSpan timeout) at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) at System.ServiceModel.ServiceHostBase.OnOpen(TimeSpan timeout) at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) at System.ServiceModel.Security.SecuritySessionSecurityTokenAuthenticator.OnOpen(TimeSpan timeout) at System.ServiceModel.Security.WrapperSecurityCommunicationObject.OnOpen(TimeSpan timeout) at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) at System.ServiceModel.Security.CommunicationObjectSecurityTokenAuthenticator.Open(TimeSpan timeout) at System.ServiceModel.Security.SecuritySessionServerSettings.OnOpen(TimeSpan timeout) at System.ServiceModel.Security.WrapperSecurityCommunicationObject.OnOpen(TimeSpan timeout) at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) at System.ServiceModel.Security.SecurityListenerSettingsLifetimeManager.Open(TimeSpan timeout) at System.ServiceModel.Channels.SecurityChannelListener
1.OnOpen(TimeSpan timeout) at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) at System.ServiceModel.Dispatcher.ChannelDispatcher.OnOpen(TimeSpan timeout)[InvalidOperationException]: 'http://localhost:8080/bookservice/' 的 ChannelDispatcher 与合同 '"IBookStore"' 无法打开其 IChannelListener。在 System.ServiceModel.Dispatcher.ChannelDispatcher.OnOpen(TimeSpan timeout) 在 System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) 在 System.ServiceModel.ServiceHostBase.OnOpen(TimeSpan timeout) 在 System.ServiceModel.Channels.CommunicationObject.Open (时间跨度超时)在 System.ServiceModel.ServiceHostingEnvironment.HostingManager.ActivateService(ServiceActivationInfo serviceActivationInfo,EventTraceActivity eventTraceActivity)在 System.ServiceModel.ServiceHostingEnvironment.HostingManager.EnsureServiceAvailable(字符串 normalizedVirtualPath,EventTraceActivity eventTraceActivity)[ServiceActivationException]:服务'/BookStoreImpl.svc'编译时出现异常,无法激活。异常消息是: 'http://localhost:8080/bookservice/' 的 ChannelDispatcher 与合同 '"IBookStore"' 无法在 System.ServiceModel 的 System.Runtime.AsyncResult.End[TAsyncResult](IAsyncResult 结果) 打开其 IChannelListener.. .Activation.HostedHttpRequestAsyncResult.End(IAsyncResult result) at System.ServiceModel.Activation.ServiceHttpModule.EndProcessRequest(IAsyncResult ar) at System.Web.HttpApplication.AsyncEventExecutionStep.OnAsyncEventCompletion(IAsyncResult ar)-->--。”
【问题讨论】:
请阅读How to Ask 并显示实际错误。同时显示您为解决该错误所做的尝试。 看起来配置有问题,因为正如我所说,一切编译良好,项目在 Visual Studio 中运行。我尝试使用配置文件并根据我在互联网和 Stack Overflow 中看到的帖子对其进行调整,但他们没有解决。 您可以随心所欲地玩,但显示实际错误会尽快解决您的问题。 我添加了错误截图。我可以从某个地方获得任何其他数据吗?没有崩溃或编译错误,只有这个。 这通常意味着发生了序列化错误。 Enable tracing 并找到正在发生的异常。 【参考方案1】:您的 WCF 托管似乎有问题。
WCF 服务应该在某个主机内运行。它可以是控制台应用程序、ASP.NET 应用程序、Windows 服务等。
在您尝试访问 url http://localhost:8080/bookservice/ 之前,您是否已将您的服务部署为具有指定地址的 IIS 应用程序?
您很可能只是在 Visual Studio 的调试下启动应用程序。在这种情况下,您应该检查项目 url 是否配置正确。 打开项目属性,Web 选项卡。 'Project Url' 编辑框中指定的地址是什么?
默认情况下,VS 会放 'localhost:some random port',例如:http://localhost:38577/。在您的情况下,端口很可能是从错误中看到的 59250
错误:无法从 http://localhost:59250/BookStoreImpl.svc
如果是这种情况并且您想坚持您的 Web.config,则将此值更改为 http://localhost:8080/bookservice/,按“创建虚拟目录”并重新启动调试会话。然后再次尝试访问GetBooksList
方法。
【讨论】:
【参考方案2】:要查看基本绑定是否有效,您可以进行此更改。
<service behaviorConfiguration="MyServiceBehavior" name="BookStore.BookStoreImpl">
<endpoint address=""
behaviorConfiguration="WebBehavior"
binding="basicHttpBinding"
bindingConfiguration="HttpBinding"
contract="BookStore.IBookStore">
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
【讨论】:
以上是关于通过 HTTP 访问 WCF 服务的主要内容,如果未能解决你的问题,请参考以下文章