[英]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);
}
}
稍后,您可以通過調用Close
來Close
_host
實例。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.