簡體   English   中英

在Windows窗體中創建一個自托管的WCF服務

[英]Create a self hosted WCF Service inside a Windows Form

如果我將此代碼用於在控制台應用程序中自托管WCF服務,則它將起作用。 我運行主機應用程序,然后從另一個應用程序(我稱為客戶端應用程序)運行,我可以從Visual Studio>解決方案資源管理器>添加服務引用> http://10.131.131.14:8080/sendKioskMessage添加服務引用>單擊“執行” ,毫無問題地添加服務,然后從客戶端應用程序使用它(這是Windows窗體)

但是,如果我在Windows窗體中運行相同的代碼,則首先運行(SELF HOST WCF)Windows窗體應用程序,然后從Visual Studio中的另一個應用程序(客戶端應用程序)運行,我嘗試在解決方案中添加“添加服務引用”中的服務引用資源管理器(與之前使用Console App自身托管的方式相同),但是會引發以下錯誤:

*

嘗試在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。 我也使用本地主機而不是實際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);
            }
        }
    }

控制台應用程序代碼(Works!我可以從其他客戶端應用程序添加服務):

[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();

...之后服務被拆除。 在此之前,您的其他客戶端可以很好地連接並添加Service References

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);
     }
 }

稍后,您可以通過調用CloseClose _host實例。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM