将 WCF 服务添加到现有应用程序?

Posted

技术标签:

【中文标题】将 WCF 服务添加到现有应用程序?【英文标题】:Adding WCF service to existing application? 【发布时间】:2011-06-29 20:28:16 【问题描述】:

我有一个现有的应用程序,现在需要从移动设备进行交互。移动设备具有 wifi 连接,并将连接到在 LAN 上托管主应用程序的 PC。移动设备只需要添加/编辑/查找/删除主应用程序维护的对象。主应用程序已经将他的功能封装在一些简单的存储库类中。

我相信这种方法是向主应用程序添加 WCF 服务,该服务公开一组移动设备可以调用的方法。但是我今天查看了 WCF 并尝试设置一个示例应用程序,但是当调用 WCF 方法时它无法访问任何数据,因此我觉得 WCF 服务正在其自己的应用程序域中运行,因此无法访问主应用程序中的相同静态类。

如果我在 VS 2008/2010 中设置了 WCF 服务项目,如何在与主 WinForms 应用程序相同的应用程序域下运行它,以便 LAN 上的远程应用程序可以与其通信以从应用程序获取数据.

下面是我的示例 WinForm

using System;
using System.ServiceModel;
using System.Windows.Forms;
using DataProject;

namespace WindowsFormsApplication1

    public partial class Form1 : Form
    
        public TestDataProject.DataStore Datastore = TestDataProject.DataStore.GetInstance();

        public Form1()
        
            InitializeComponent();
            Datastore.Add(new MyObj  ID = 1, Data = "hello" );
            Datastore.Add(new MyObj  ID = 2, Data = "world" );
            Datastore.Add(new MyObj  ID = 3, Data = "item3" );
            Datastore.Add(new MyObj  ID = 4, Data = "item4" );
            Datastore.Add(new MyObj  ID = 5, Data = "fiver" );
        
    

我需要从 WCF 服务中获得对 TestDataProject.DataStore.GetInstance() 的访问权限;

编辑

我做到了

using System;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Windows.Forms;
using DataProject;
using TestDataProject;

namespace WindowsFormsApplication1

    public partial class Form1 : Form
    
        public TestDataProject.DataStore Datastore = TestDataProject.DataStore.GetInstance();

        public Form1()
        
            InitializeComponent();
            Datastore.Add(new MyObj  ID = 1, Data = "hello" );
            Datastore.Add(new MyObj  ID = 2, Data = "world" );
            Datastore.Add(new MyObj  ID = 3, Data = "item3" );
            Datastore.Add(new MyObj  ID = 4, Data = "item4" );
            Datastore.Add(new MyObj  ID = 5, Data = "fiver" );

            ServiceHost host = new ServiceHost(typeof(SimpleService),
                new Uri("http://localhost:8001/MetadataSample"));
            try
            
                // Check to see if the service host already has a ServiceMetadataBehavior
                ServiceMetadataBehavior smb = host.Description.Behaviors.Find<ServiceMetadataBehavior>();
                // If not, add one
                if (smb == null)
                    smb = new ServiceMetadataBehavior();
                smb.HttpGetEnabled = true;
                smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
                host.Description.Behaviors.Add(smb);
                // Add MEX endpoint
                host.AddServiceEndpoint(
                  ServiceMetadataBehavior.MexContractName,
                  MetadataExchangeBindings.CreateMexHttpBinding(),
                  "mex"
                );
                // Add application endpoint
                host.AddServiceEndpoint(typeof(ISimpleService), new WSHttpBinding(), "");

                // Open the service host to accept incoming calls
                host.Open();

                // The service can now be accessed.
                Console.WriteLine("The service is ready.");
                Console.WriteLine("Press <ENTER> to terminate service.");
                Console.WriteLine();
                Console.ReadLine();

                // Close the ServiceHostBase to shutdown the service.
                //host.Close();
            
            catch (CommunicationException commProblem)
            
                Console.WriteLine("There was a communication problem. " + commProblem.Message);
                Console.Read();
            

        

        public void Display(string msg)
        
            MessageBox.Show(msg);
        
    

    [ServiceContract]
    public interface ISimpleService
    
        [OperationContract]
        string Test();

        [OperationContract]
        string GetOBJDesc(int id);

        [OperationContract]
        MyObj GetObject(int id);
    

    public class SimpleService : ISimpleService
    
        #region Implementation of ISimpleService

        public string Test()
        
            return "Hello world";
        

        public string GetOBJDesc(int value)
        
            MyObj obj = DataStore.GetInstance().Get(value);
            if (obj != null)
            
                return obj.Data;
            
            return "";
        

        public MyObj GetObject(int id)
        
            return DataStore.GetInstance().Get(id);
        

        #endregion
    

与 app.config 包含

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <services>
      <service name="WindowsFormsApplication1.SimpleService">
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="SimpleServiceBehavior">
          <serviceMetadata httpGetEnabled="True" policyVersion="Policy15" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

然后我可以在 url http://localhost:8001/MetadataSample 上使用 WCF 测试客户端

我遇到的主要问题是我的服务自动启动,这可以通过项目设置在 VS2010 中禁用。另一个问题是 UAC,鉴于 Visual Studio 未设置为管理员,调试器无法托管服务,这是通过添加包含

的 WindowsFormApplication1.MANIFEST 文件来解决的
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">”
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">”
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level="requireAdministrator"/>
      </requestedPrivileges>
    </security>
  </trustInfo>
</assembly>

【问题讨论】:

听起来“WCF 服务”可能是指在 IIS/Web 服务器上下文中运行的 WCF Web 服务。您创建的 WCF 服务是否确实在 Windows 窗体进程中运行? @Kragen,我认为不是,这可能是问题所在。我在 Visual Studio 中创建了一个新的 WCF 项目(文件 -> 新建 -> 项目 -> WCF 服务应用程序)在服务联系人中,我定义了一组测试方法,但它们返回的数据与表单包含的数据不同。表单可以访问存储库中的 5 个对象,但“相同”存储库有 0 个用于 WCF 服务的对象。通过 GetInstance 访问存储库,以确保它们具有相同的引用。 【参考方案1】:

您已经创建了一个 WCF Web 服务项目,它将在 Web 服务进程(通常是 IIS)内运行,而不是在您的 Windows 窗体进程内,因此它无法访问静态类和属性中的任何数据Windows 窗体进程。

听起来您最简单的选择是将 WCF 服务托管在您的 Windows 窗体应用程序中。我不想详细介绍如何执行此操作,因为网络上已经有许多可用资源(我也很难声称自己是专家!),但您可能想尝试以下文章作为起点:

Hosting WCF services in a Windows Forms Application

【讨论】:

我会阅读链接并更新问题。我今天已经阅读了相当多的 WCF 教程,也许是我赶时间? 它没有给我一个可行的解决方案,但我已经设法从该链接和其他教程中收集了一些东西。我需要找到的术语是自托管 WCF 服务。【参考方案2】:

WCF 服务与应用程序的其余部分部署在同一程序集中,并且应该能够访问其中的任何类。也许您使用了不同的命名空间。如果是这种情况,请使用完全限定名称或 using 语句。

【讨论】:

以上是关于将 WCF 服务添加到现有应用程序?的主要内容,如果未能解决你的问题,请参考以下文章

将 DataMember 添加到 WCF 中的现有 DataContract

将 WCF SOAP 和 WCF REST 服务托管为 Azure 应用服务

如何在现有 WCF 服务中创建新方法?

是否可以在不添加服务参考的情况下访问 WCF 服务?

在现有 WCF SOAP 服务中添加 Http 标头不起作用

在 MVC Web 应用程序中托管 WCF 服务