首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在Windows窗体内创建自托管WCF服务

在Windows窗体内创建自托管WCF服务
EN

Stack Overflow用户
提问于 2018-09-27 06:54:45
回答 1查看 1.1K关注 0票数 1

如果我将此代码用于控制台应用程序中的self Host 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是运行这两个应用程序的pc的IP。我也使用localhost而不是我的实际IP,结果是相同的。

Windows窗体代码(无法从其他应用程序添加服务):

代码语言:javascript
复制
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);
            }
        }
    }

控制台应用程序代码(有效!我可以从其他客户端应用程序添加服务):

代码语言:javascript
复制
[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从,因为我需要自己托管的WCF服务从一个windows窗体,没有一个控制台应用程序。

我使用的是Visual Studio 2017,.Net框架4.6.1

提前感谢各位!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-09-27 07:21:24

TL;DR控制台应用程序之所以能工作,是因为您在关闭服务之前有延迟;而WinForms主机则不能

代码语言:javascript
复制
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();

服务被中断的...after。在此之前,您的其他客户端可以很好地连接并添加服务引用。

WinForms应用程序没有这样的延迟:

代码语言:javascript
复制
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块的作用域时,...it会立即关闭。using将自动调用host对象上的Dispose(),该对象依次调用Close()

考虑将主机放入一个变量中,如下所示:

代码语言:javascript
复制
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实例。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52527074

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档