如果我将此代码用于在控制台应用程序中自承载 WCF 服务,它可以工作。我运行主机应用程序,然后从另一个应用程序(我称之为客户端应用程序(我可以从 Visual Studio>解决方案资源管理器添加服务引用>添加服务引用> http://10.131.131.14:8080/sendKioskMessage>单击"转到",毫无问题地添加服务并从客户端应用程序(这是一个 Windows 窗体(使用它
但是,如果我在 Windows 窗体中运行相同的代码,则首先运行(自主机 WCF(Windows 窗体应用,然后从 Visual Studio 中的另一个应用(客户端应用(运行,我尝试从解决方案资源管理器中的"添加服务引用"中添加服务引用(与之前的工作方式相同,但与控制台应用自主机相同(,但它会引发以下错误:
*
尝试在 http://10.131.131.14:8080/sendKioskMessage。
(如果我单击详细信息链接,则显示以下内容:(
下载时出错 "http://10.131.131.14:8080/sendKioskMessage/$metadata"。无法 连接到远程服务器。元数据包含引用 无法解析:"http://10.131.131.14:8080/sendKioskMessage"。 没有端点侦听 http://10.131.131.14:8080/sendKioskMessage 可以接受 消息。这通常是由不正确的地址或 SOAP 操作引起的。 有关更多详细信息,请参阅 InnerException(如果存在(。无法连接到 远程服务器。如果在当前解决方案中定义了服务, 尝试生成解决方案并再次添加服务引用。
*
我使用的 IP 是运行两个应用程序的电脑的 IP。我还使用了本地主机而不是我的实际 IP,结果相同。
Windows 窗体代码(无法从其他应用添加服务(:
public partial class KioskosServerForm : Form
{
[ServiceContract]
public interface IKioskMessageService
{
[OperationContract]
string SendKioskMessage(string message);
}
public class KioskMessageService : IKioskMessageService
{
public string SendKioskMessage(string message)
{
return string.Format("Message sent: {0}", message);
}
}
public KioskosServerForm()
{
InitializeComponent();
}
private void KioskosServerForm_Load(object sender, EventArgs e)
{
Uri baseAddress = new Uri("http://10.131.131.14:8080/sendKioskMessage");
try
{
// Create the ServiceHost.
using (ServiceHost host = new ServiceHost(typeof(KioskMessageService), baseAddress))
{
// Enable metadata publishing.
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
host.Description.Behaviors.Add(smb);
// Open the ServiceHost to start listening for messages. Since
// no endpoints are explicitly configured, the runtime will create
// one endpoint per base address for each service contract implemented
// by the service.
host.Open();
}
}
catch (Exception exp)
{
MessageBox.Show(exp.InnerException.Message);
}
}
}
控制台应用代码(有效!我可以从其他客户端应用程序添加服务(:
[ServiceContract]
public interface IKioskMessageService
{
[OperationContract]
string SendKioskMessage(string message);
}
public class KioskMessageService : IKioskMessageService
{
public string SendKioskMessage(string message)
{
return string.Format("Message sent: {0}", message);
}
}
class Program
{
static void Main(string[] args)
{
Uri baseAddress = new Uri("http://localhost:8080/sendKioskMessage");
// Create the ServiceHost.
using (ServiceHost host = new ServiceHost(typeof(KioskMessageService),baseAddress))
{
// Enable metadata publishing.
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
host.Description.Behaviors.Add(smb);
// Open the ServiceHost to start listening for messages. Since
// no endpoints are explicitly configured, the runtime will create
// one endpoint per base address for each service contract implemented
// by the service.
host.Open();
Console.WriteLine("The service is ready at {0}", baseAddress);
Console.WriteLine("Press <Enter> to stop the service.");
Console.ReadLine();
// Close the ServiceHost.
host.Close();
}
}
}
我不知道如果服务在控制台应用中自承载,为什么可以使用该服务,但如果该服务在 Windows 窗体中自承载,则无法添加该服务。
我将非常感谢您帮助从 Windows From 实现此目的,因为我需要从 Windows 窗体(而不是控制台应用程序(自承载 WCF 服务。
我正在使用Visual Studio 2017,.Net Framework 4.6.1
提前感谢伙计们!!
TL;DR控制台应用工作是因为您在关闭服务之前有延迟;WinForms 主机没有
控制台 WCF 主机服务正常工作的原因是,启动宿主并继续,直到Console.ReadLine()
行:
host.Open();
Console.WriteLine("The service is ready at {0}", baseAddress);
Console.WriteLine("Press <Enter> to stop the service.");
Console.ReadLine(); // <-------- program waits here
// Close the ServiceHost.
host.Close();
。之后,服务被拆除。 在此之前,您的其他客户端可以正常连接并添加服务引用。
WinForms 应用程序没有这样的延迟:
private void KioskosServerForm_Load(object sender, EventArgs e)
{
Uri baseAddress = new Uri("http://10.131.131.14:8080/sendKioskMessage");
try
{
// Create the ServiceHost.
using (ServiceHost host = new ServiceHost(typeof(KioskMessageService), baseAddress))
{
// Enable metadata publishing.
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
host.Description.Behaviors.Add(smb);
// Open the ServiceHost to start listening for messages. Since
// no endpoints are explicitly configured, the runtime will create
// one endpoint per base address for each service contract implemented
// by the service.
host.Open(); // <------ opened here
} // <------ shutdown here
}
catch (Exception exp)
{
MessageBox.Show(exp.InnerException.Message);
}
}
。当代码超出using
块的范围时,它会立即关闭。using
将自动调用host
对象上的Dispose()
,而对象又调用Close()
。
考虑将主机放入变量中,如下所示:
ServiceHost _host; // <---------- new!
private void KioskosServerForm_Load(object sender, EventArgs e)
{
Uri baseAddress = new Uri("http://10.131.131.14:8080/sendKioskMessage");
try
{
// Create the ServiceHost.
_host = new ServiceHost(typeof(KioskMessageService), baseAddress))
// Enable metadata publishing.
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
_host.Description.Behaviors.Add(smb);
// Open the ServiceHost to start listening for messages. Since
// no endpoints are explicitly configured, the runtime will create
// one endpoint per base address for each service contract implemented
// by the service.
_host.Open();
}
catch (Exception exp)
{
MessageBox.Show(exp.InnerException.Message);
}
}
稍后,您可以通过调用Close
来关闭_host
实例。