我正在学习如何使用WCF,我正在尝试从头开始编写一个小的HelloWorld程序(主机和客户端)。每当我的客户尝试使用该服务时,我都会收到ProtocolException Unhandled
,而我无法弄清楚原因。我正在使用IIS托管该服务。
关于设置方式的方式:我正在尽力将客户端,代理,主机,服务和合同分开,如video中所详述,并按照article中的说明进行操作。基本上我在解决方案中为每个项目提供了不同的项目。
以下是一些不同的文件,显示了我在说什么:
namespace HelloWorld
{
public class HelloWorldService : IHelloWorldService
{
public String GetMessage(String name)
{
return "Hello World from " + name + "!";
}
}
}
namespace HelloWorld
{
[ServiceContract]
public interface IHelloWorldService
{
[OperationContract]
String GetMessage(String name);
}
}
namespace HelloWorld
{
public class Proxy : ClientBase<IHelloWorldService>, IHelloWorldService
{
#region IHelloWorldService Members
public String GetMessage(String name)
{
return Channel.GetMessage(name);
}
#endregion
}
}
namespace Client
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click_1(object sender, EventArgs e)
{
Proxy proxy = new Proxy();
MessageBox.Show(proxy.GetMessage(textBox1.Text));
}
}
}
客户端只是一个带有文本框和按钮的表单,它尝试使用文本框中的任何内容作为参数执行GetMessage()。还有另一个类实际上创建了表单的实例。
这是我的网站web.config:
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceTypeBehaviors">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="HelloWorld.HelloWorldService" behaviorConfiguration="MyServiceTypeBehaviors">
<endpoint address="http://localhost:8002/" binding="basicHttpBinding" contract="HelloWorld.IHelloWorldService"/>
<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex"/>
</service>
</services>
</system.serviceModel>
</configuration>
这是我的app.config与客户端:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<client>
<endpoint address="http://localhost:8002/" binding="basicHttpBinding" contract="HelloWorld.IHelloWorldService" />
</client>
</system.serviceModel>
</configuration>
我的svc文件很短,只是:
<%@ServiceHost Service="HelloWorld.HelloWorldService"%>
我知道该服务正在运行,因为当我在浏览器中导航到http://localhost:8002/HelloWorldService.svc
时,我会看到显示
您已创建了一项服务。
要测试此服务,您需要创建一个客户端并将其用于 打电话给服务。
所以这里出现了障碍:服务正在使用IIS运行,我启动客户端实例,带文本框和按钮的窗口出现,我输入一些字母,点击按钮,然后程序崩溃,我得到ProtocolException Unhandled, (405) Method not allowed.
错误发生在Proxy类的这一行:
return Channel.GetMessage(name);
我一直试图解决这个问题几个小时,而且我没有取得多大进展。如果有人能够至少指出我正确的方向,我将非常感激。
最后一件事:我想从头开始编写客户端和代理,而不使用svcutil.exe。
答案 0 :(得分:72)
当你转到基地址(.svc)时它工作的原因是这是一个HTTP GET操作来获取服务的元数据。当您在服务合同上调用方法时,您正在进行POST操作,而且很可能您没有启用此功能。根据您要定位的.NET版本,将以红色突出显示其中一个。
答案 1 :(得分:4)
您必须在客户端配置的端点标记中指定服务的完整地址。 像这样:
<endpoint address="http://localhost:8002/HelloWorldService.svc" binding="basicHttpBinding" contract="HelloWorld.IHelloWorldService" />
不要忘记在端点标记的地址属性中添加'。svc'扩展名后面的服务名称。它对我有用。希望你现在能得到解决方案。
客户端配置如下所示:
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IService"/>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:61569/Service1.svc" binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_IService" contract="WcfServiceApp.IService1" name="WSHttpBinding_IService"/>
</client>
答案 2 :(得分:2)
您必须在客户端配置的端点标记中指定服务的完整地址
address =“http:// localhost:8002 / HelloWorldService.svc”,您可以在其中放置相同的端点配置。
当我陷入地狱时,它对我有用......
答案 3 :(得分:1)
好的,找到了解决方案,虽然我不完全确定它的工作原理。我想当你使用Cassini或IIS或任何东西来托管网站时,你不应该在web.config文件中的端点中指定一个地址。我所要做的就是将其更改为address=""
并开始正常工作。请务必确保服务器托管服务的端口与app.config文件中的代码匹配。