Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding WCF service to existing application?

I have an existing application which now has the requirement to be interacted with from a mobile device. The mobile device has a wifi connection, and would be connecting to the PC hosting the main application on a LAN. The mobile device simply needs to add/edit/find/delete objects the main application is maintaining. The main application already encapsulates his functionality in some simple repository classes.

I believe the approach would be to add a WCF service to the main application which exposes a set of methods the mobile device can call against. However I have looked up WCF today and tried to setup an example application, but when called the WCF methods it is unable to access any data, as such I feel the WCF service is running in its own application domain and as such has no access to the same static classes in the main application.

If I setup a WCF service project in VS 2008/2010, how can I run it under the same application domain as the main WinForms application, so that a remote application on the LAN can communicate with it to get data from the application.

Below is my sample 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" });
        }
    }
}

What I need from a WCF service, is access to TestDataProject.DataStore.GetInstance();

Edit

I achieved this by

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

With app.config containing

<?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>

I could then use WCF Test Client on the url http://localhost:8001/MetadataSample

The main issue I suffered from was my Service starting automatically, this can be disabled in VS2010 by a project setting. And the other issue was UAC, given Visual studio was not set to be a administrator the debugger failed to host a service, this was fixed by adding a WindowsFormApplication1.MANIFEST file containing

<?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>
like image 472
JonWillis Avatar asked Feb 18 '11 13:02

JonWillis


People also ask

How use WCF service in Windows form application?

Reference the WCF serviceOn the File menu, point to Add and then click New Project. In the New Project dialog box, expand the Visual Basic or Visual C# node, select Windows, and then select Windows Forms Application. Click OK to open the project. Right-click WindowsApplication1 and click Add Service Reference.


2 Answers

You have created a WCF Web Service project, which will be running inside the web service process (normally IIS), not inside your windows forms process and so it won't have any access to any data in static classes and properties in the Windows Forms process.

It sounds like your simplest option is to host the WCF service inside your windows forms application instead. I don't want to go into too much detail on how to do this as there are a number of resources already available on the web (also I can hardly claim to be an expert!), but you might want to try the following article as a starting point:

  • Hosting WCF services in a Windows Forms Application
like image 194
Justin Avatar answered Sep 20 '22 19:09

Justin


WCF services are deployed in the same assembly as the rest of the application and should be able to access any classes in it. Perhaps you have used a different namespace. If this is the case, use a fully qualified name or a using statement.

like image 20
kgiannakakis Avatar answered Sep 21 '22 19:09

kgiannakakis