Hosting WCF service via ServiceHost in Console/WinForms

amaranth picture amaranth · Oct 18, 2013 · Viewed 8.8k times · Source

I'm hosting WCF service in console application (.NET 4.0). Service code (from msdn example):

using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;

namespace WCFServiceHost
{
    [ServiceContract(Namespace = "WCFServiceHost")]
    public interface ICalculator
    {
        [WebInvoke(ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped)]
        MathResult DoMathJson(double n1, double n2);

        [WebInvoke(ResponseFormat = WebMessageFormat.Xml, BodyStyle = WebMessageBodyStyle.Wrapped)]
        MathResult DoMathXml(double n1, double n2);

    }

    public class CalculatorService : ICalculator
    {

        public MathResult DoMathJson(double n1, double n2)
        {
            return DoMath(n1, n2);
        }

        public MathResult DoMathXml(double n1, double n2)
        {
            return DoMath(n1, n2);
        }

        private MathResult DoMath(double n1, double n2)
        {
            MathResult mr = new MathResult();
            mr.sum = n1 + n2;
            mr.difference = n1 - n2;
            mr.product = n1 * n2;
            mr.quotient = n1 / n2;
            return mr;
        }
    }

    [DataContract]
    public class MathResult
    {
        [DataMember]
        public double sum;

        [DataMember]
        public double difference;

        [DataMember]
        public double product;

        [DataMember]
        public double quotient;
    }
}

Next the console app code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;

namespace WCFServiceHost
{
    class Program
    {
        public static void Main()
        {
            var adrs = new Uri[1];
            adrs[0] = new Uri("http://localhost:3980");
            using (ServiceHost serviceHost = new ServiceHost(typeof(CalculatorService), adrs))
            {
                try
                {
                    // Open the ServiceHost to start listening for messages.
                    serviceHost.Open();

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

                    // Close the ServiceHost.
                    serviceHost.Close();
                }
                catch (TimeoutException timeProblem)
                {
                    Console.WriteLine(timeProblem.Message);
                    Console.ReadLine();
                }
                catch (CommunicationException commProblem)
                {
                    Console.WriteLine(commProblem.Message);
                    Console.ReadLine();
                }
            }
        }
    }
}

And my 2 questions:

1. When I'm open _http://localhost:3980 I've get: enter image description here How to enable metadata publishing? See Dai Bok answer.

  1. Now how to get data from this service - (to get data from service like in msdn example)? Embed any web framework (like Nancy) or use HttpListener?

Answer

Dai Bok picture Dai Bok · Oct 18, 2013

You need to make sure you WCF web config is set up correctly

You will need to enable metat data for http gets, check you web config in the system.serviceModel -> behaviors -> serviceBehaviors -> behavior -> serviceMetadata

and make sure you have:

<serviceMetadata httpGetEnabled="true"/>

For Part 2, you can get the data, you can do something like

   public MathResult GetResult(int a, int b) {
        var status = new MathResult();
        try {
                    var myBinding = new WSHttpBinding();
                    var myEndpoint =
                        new EndpointAddress(
                            new Uri("http://localhost:3980/"));
                    var myChannelFactory = new ChannelFactory<ICalculator>(myBinding, myEndpoint);
                    ICalculator client = myChannelFactory.CreateChannel();
            status = client.DoMathJson(a,b);
        } catch (Exception e) {
            //do something proper here 
        }
        return status;
    }