9

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>
JonWillis
  • 3,146
  • 5
  • 32
  • 54
  • It sounds like by "WCF service" you might be referring to a WCF web service running in the context of IIS / the web server. Is your WCF service you have created definitely running inside the windows forms process? – Justin Feb 18 '11 at 14:01
  • @Kragen, I do not think it is, which maybe the issue. I created a new WCF project in visual studio (File - > New - > Project -> WCF Service Application) In the service contacts I defined a set of test methods, but they do not return the same data as the form contains. Form has access to 5 objects in a repository, but the "same" repository has 0 objects for the WCF service. The repository is accessed via a GetInstance to ensure they have the same reference. – JonWillis Feb 18 '11 at 14:06

2 Answers2

4

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:

Justin
  • 84,773
  • 49
  • 224
  • 367
  • Ill have a read into the link, and update the question. I've read a fair few WCF tutorials today, maybe I rushed in to fast? – JonWillis Feb 18 '11 at 14:21
  • It didnt give me a working solution, but I have managed to put something together taking parts from that link and other tutorials. The term i needed to find was self-hosted WCF services. – JonWillis Feb 18 '11 at 17:13
2

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.

kgiannakakis
  • 103,016
  • 27
  • 158
  • 194