WCF Self Host Service - Endpoints in C#

2019-01-25 13:10发布

问题:

My first few attempts at creating a self hosted service. Trying to make something up which will accept a query string and return some text but have have a few issues:

  • All the documentation talks about endpoints being created automatically for each base address if they are not found in a config file. This doesn't seem to be the case for me, I get the "Service has zero application endpoints..." exception. Manually specifying a base endpoint as below seems to resolve this:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ServiceModel;
    using System.ServiceModel.Description;
    
    namespace TestService
    {
        [ServiceContract]
        public interface IHelloWorldService
        {
           [OperationContract]
           string SayHello(string name);
        }
    
        public class HelloWorldService : IHelloWorldService
        {
            public string SayHello(string name)
            {
               return string.Format("Hello, {0}", name);
            }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                string baseaddr = "http://localhost:8080/HelloWorldService/";
                Uri baseAddress = new Uri(baseaddr);
    
                // Create the ServiceHost.
                using (ServiceHost host = new ServiceHost(typeof(HelloWorldService), baseAddress))
                {
                    // Enable metadata publishing.
                    ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
                    smb.HttpGetEnabled = true;
                    smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
                    host.Description.Behaviors.Add(smb);
    
                    host.AddServiceEndpoint(typeof(IHelloWorldService), new BasicHttpBinding(), baseaddr);
                    host.AddServiceEndpoint(typeof(IHelloWorldService), new BasicHttpBinding(), baseaddr + "SayHello");
    
                    //for some reason a default endpoint does not get created here
                    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();
                }
             }
         }
    }
    
  • How would I go about setting this up to return the value of name in SayHello(string name) when requested thusly: localhost:8080/HelloWorldService/SayHello?name=kyle

I'm trying to walk before running, but this just seems like crawling...

回答1:

For your question about default endpoints not being added:

  • first of all, that's a WCF 4 feature - it will work on .NET 4 only
  • next, the default endpoints are only added to your service host if you have no explicit endpoints defined in config, and if you do not add endpoints yourself in code! By adding those two endpoints in code, you're taking charge and the WCF 4 runtime will not fiddle with your config

Check out this MSDN library article for more information on What's new in WCF 4 for developers. It shows, among other things, how to use default endpoints - you basically define a base address for your service and open the ServiceHost - that's all!

string baseaddr = "http://localhost:8080/HelloWorldService/";
Uri baseAddress = new Uri(baseaddr);

// Create the ServiceHost.
using (ServiceHost host = new ServiceHost(typeof(HelloWorldService), baseAddress))
{
   //for some reason a default endpoint does not get created here
   host.Open();

   // here, you should now have one endpoint for each contract and binding
}

You can also add the default endpoints explicitly, in code, if you wish to do so. So if you need to add your own endpoints, but then you want to add the system default endpoints, you can use:

// define and add your own endpoints here

// Create the ServiceHost.
using (ServiceHost host = new ServiceHost(typeof(HelloWorldService), baseAddress))
{
   // add all the system default endpoints to your host
   host.AddDefaultEndpoints();

   //for some reason a default endpoint does not get created here
   host.Open();

   // here, you should now have your own endpoints, plus 
   // one endpoint for each contract and binding
}

I also fonud this blog post here to be quite illuminating - Christopher's blog is full of good and very helpful WCF posts - highly recommended.



回答2:

As for books - here's my recommendation: the book I always recommend to get up and running in WCF quickly is Learning WCF by Michele Leroux Bustamante. She covers all the necessary topics, and in a very understandable and approachable way. This will teach you everything - basics, intermediate topics, security, transaction control and so forth - that you need to know to write high quality, useful WCF services.

Learning WCF http://ecx.images-amazon.com/images/I/41wYa%2BNiPML._BO2,204,203,200_PIsitb-sticker-arrow-click,TopRight,35,-76_AA240_SH20_OU01_.jpg

The more advanced topics and more in-depth look at WCF will be covered by Programming WCF Services by Juval Lowy. He really dives into all technical details and topics and presents "the bible" for WCF programming.

Programming WCF Services http://ecx.images-amazon.com/images/I/41H2u13a9bL._BO2,204,203,200_PIsitb-sticker-arrow-click,TopRight,35,-76_AA240_SH20_OU01_.jpg



回答3:

If IIS hosts your web service, then you get the friendly "you have created a web service" page, assuming nothing else is wrong. You might want to try some quick WCF tutorials, as can be found in Bustamente's Learning WCF book, they go fast and explain a lot.

EDIT: Here's an MSDN page which shows one way to get query string parameters off of your requested service call, nice example. It shows the use of [WebGet] attribute. If you didn't want to use that, you could try using OperationContext to get at the incoming request's internals.