WebAPI Fall Update 2012 : ResultLimit support on Queryable

In case you have missed this hidden gem from the update, Queryable now supports following four properties. I will cover other properties in separate blog post.

  • ResultLimit
  • StableOrdering
  • LamdaNestingLimit
  • HandleNullPropogation

Having support for ResultLimit is really great news for people using oData support in WebAPI.

This means that you can now set the upper limit on the amount of records that will be returned for a given resource when you apply Queryable attribute. This is very important step to make sure that the client of your API don’t unnecessarily run large queries therby limiting the system scalability.

If you want this capability on an existing system, ensure that oData version of API is latest. Mine is Microsoft.AspNet.WebApi.OData.0.2.0-alpha-121031\lib\net40\System.Web.Http.OData.dll. I have also applied the fall 2012 update.

Let’s say you this method on /webapi/Accounts

image1

and you perform simple Get operation /webapi.

image2

This returns count of 3.

Now add the ResultLimit property on Queryable  Attribute and set this value to 2.

image3

Let’s execute the same query again.

image4

It returns 2 as expected.

Advertisements

Whitepaper: Introduction to Windows Store Apps & WinRT

Windows 8 is big step forward in the evolution of Modern touch friendly User interface – never seen before since Windows 95.

With the release of Windows 8, Microsoft has also released Visual studio 2012 and a new runtime from ground up called WinRT. It presents a significant opportunity for a variety of developers from different backgrounds to take advantage of consistent, easy to use API and ultimately be able to sell their apps on the Windows 8 Store.

I have written a whitepaper on the subject.

Hope you like it.

Getting Started with self-hosting SignalR using PersistentConnection

SignalR is a great library to help build real-time, single/multi user apps.
Although SignalR is very well documented, I wanted to write a compact sample which demonstrates Client and Server using PersistentConnection.

I have specifically chosen not to use Hub for this demo as there are many samples out there already.

Step 1
Create a console project.

Step 2
Add following nuget packages
SignalR.Hosting.Self
SignalR.Client

Step 3
To create instance of server, pass the url in the Server class’s constructor. Map the connection. Please make sure that you provide “/” at the end in the url.

You then call MapConnection method with a name of the path. This means that now your client connection becomes Url+Path.

Note MapConnection takes a type ‘T’ where T: PersistentConnection. Since PersistentConnection is an abstract class, you typically inherit from PersistentConnection and that becomes the entry point where the client calls arrives. See below a class called ‘MyConnection’

Next you create instance of Client.Connection class, Be careful, there is a connection class in the server as well so you may have to qualify it with Client.Connection here.

Client side events

‘Received’ is called when Server calls you back
‘StateChanged’ is called when the Connection state changes

SourceCode_image1

Step 4
To call server, call “Start” method on the client’s connection object which returns a task so check for the task for any problems before proceeding and then call ‘Send’ method which actually calls server. Once the Send method is executed, ‘OnReceivedAsync’ method of ‘MyConnection’ class is called. Here you can call all the client’s back by executing ‘Connection.Broadcast’ (or just use Connection.Send method calls the client that is waiting for specific signal) method

SourceCode_image2

Source code for MyConnection class

SourceCode_image3

When you run this sample, you should see output like following.

console_output

You can download sample from here

ASP.NET Web API BSON Formatter

ASP.NET Web API includes JSON.NET which includes BSON Serializer so to support BSON format it is quite easy.

  1. Create a class called BSONFormatter and inherit from MediaTypeFormatter
using Newtonsoft.Json;
using Newtonsoft.Json.Bson;

namespace WebAPI.Common.Formatter
{
     public class BsonFormatter : MediaTypeFormatter
    {
        public BsonFormatter()
        {
            SupportedMediaTypes
             .Add(new MediaTypeHeaderValue("application/bson"));
        }

        public MediaTypeHeaderValue MediaTypeHeaderValue
        {
            get 
           { 
               return new MediaTypeHeaderValue("application/bson"); 
            }
        }

        public override bool CanReadType(Type type)
        {
            return false;
        }

        public override bool CanWriteType(Type type)
        {
            return true;
         }

2. Make sure you include following namespace

using

3. Override WriteToStreamAsync method, using BsonWriter by passing the stream and using JsonSerializer to serialize.

public override Task WriteToStreamAsync(Type type,
 object value, Stream writeStream, HttpContent content,
            TransportContext transportContext)
        {
            Task task = Task.Factory.StartNew(
                () =>
                    {
                        content.Headers.ContentType = MediaTypeHeaderValue;
                        var serializer = new JsonSerializer();

                        // serialize product to BSON
                        var writer = new BsonWriter(writeStream);
                        serializer.Serialize(writer, value);
                    });

            return task;
        }

4. Plugging it in Web.API pipeline.

  var config = new HttpSelfHostConfiguration("http://localhost:8080");
    ILifetimeScope container = GetContainerLifeTimeScope();
     config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "WebAPI/{controller}/{id}",
                defaults: new {id = RouteParameter.Optional}
                );

      config.Formatters.Add(new BsonFormatter());
    config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
      using (var server = new HttpSelfHostServer(config))
      {
                server.OpenAsync().Wait();
                Console.WriteLine("Press any key to terminate");
                Console.ReadLine();
        }

5. Bson Request/Response (in fiddler)

BsonRequest BsonResponse

WCF Web API Self Hosting with Unity

WCF Web API Preview 4 has been out for sometime and most examples available today still use IIS, I think only handful of example I have found uses self hosting approach and they are too simplistic or forces your service to be singleton by passing instance so I decided to provide a sample similar to the one that is available for IIS but uses and IOC container.

Configuration looks like this.

1 static void Main(string[] args) 2 { 3 4 var container = new UnityContainer(); 5 container.RegisterType(typeof(PersonResource)); 6 container.RegisterType(typeof(PeopleResource)); 7 container.RegisterType( 8 typeof(IPersonRepository), typeof(PersonRespository), 9 new ContainerControlledLifetimeManager()); 10 11 var config = HttpHostConfiguration.Create() 12 .AddFormatters(new MediaTypeFormatter[] { new JpgFormatter() }) 13 .SetResourceFactory(new UnityFactory(container)) 14 .SetErrorHandler(new CustomErrorHandler()) 15 .SetOperationHandlerFactory(new OperationHandlerFactory()) 16 .AddMessageHandlers(typeof(LoggingChannel), 17 typeof(UriFormatExtensionMessageChannel)); 18 19 var serviceHost = new UnityHttpServiceHost(typeof(PersonResource),config, 20 new Uri("http://localhost:8090/person")) 21 {Container = container}; 22 serviceHost.Open(); 23 PrintEndpointDescription(serviceHost); 24 25 Console.WriteLine("Press any key to exit"); 26 Console.ReadLine(); 27 serviceHost.Close(); 28 }

The magic is done as a part of UnityHttpServiceHost class which sets up binding, behavior and hook into the unity pipeline.

1 public class UnityHttpServiceHost : HttpServiceHost 2 { 3 public UnityContainer Container { set; get; } 4 5 public HttpHostConfiguration Configuration { get; set; } 6 7 public UnityHttpServiceHost() 8 : base() 9 { 10 Container = new UnityContainer(); 11 } 12 13 public UnityHttpServiceHost(Type serviceType, IHttpHostConfigurationBuilder builder, Uri baseAddresses) 14 : base(serviceType, baseAddresses) 15 { 16 Container = new UnityContainer(); 17 ServiceType = serviceType; 18 if (builder == null) 19 this.Configure(new HttpHostConfiguration()); 20 else 21 Configure(builder.Configuration); 22 23 } 24 25 public Type ServiceType { get; set; } 26 27 public override void AddServiceEndpoint(ServiceEndpoint endpoint) 28 { 29 var httpEndpoint = (HttpEndpoint)endpoint; 30 httpEndpoint.Binding = new HttpBinding(); 31 if (Configuration != null) 32 { 33 httpEndpoint.OperationHandlerFactory = Configuration.OperationHandlerFactory; 34 httpEndpoint.MessageHandlerFactory = Configuration.MessageHandlerFactory; 35 if (this.Configuration.ErrorHandler != null) 36 { 37 var behavior = endpoint.Behaviors.Remove<HttpBehavior>(); 38 endpoint.Behaviors.Add(new HttpBehaviorWithErrorHandler(this.Configuration.ErrorHandler) 39 { 40 OperationHandlerFactory = this.Configuration.OperationHandlerFactory 41 }); 42 } 43 if (this.Configuration.InstanceFactory != null) 44 { 45 var behavior = 46 new InstanceProviderBehavior(new ResourceFactoryProvider(this.ServiceType, 47 this.Configuration.InstanceFactory)); 48 endpoint.Behaviors.Add(behavior); 49 } 50 } 51 base.AddServiceEndpoint(endpoint); 52 } 53 54 private void Configure(HttpHostConfiguration configuration) 55 { 56 this.Configuration = configuration; 57 this.OperationHandlerFactory = configuration.OperationHandlerFactory; 58 this.MessageHandlerFactory = configuration.MessageHandlerFactory; 59 AddDefaultEndpoints(); 60 } 61 62 protected override void OnOpening() 63 { 64 new UnityServiceBehavior(Container).AddToHost(this); 65 base.OnOpening(); 66 } 67 68 }

UnityServiceBehavior looks like following. It uses UnityInstanceProvider which implements IInstanceProvider interface to manage the lifetime of resources.

1 public class UnityServiceBehavior : IServiceBehavior 2 { 3 public UnityInstanceProvider InstanceProvider 4 { 5 get; set; 6 } 7 8 private ServiceHost serviceHost = null; 9 10 public UnityServiceBehavior() 11 { 12 InstanceProvider = new UnityInstanceProvider(); 13 } 14 public UnityServiceBehavior(UnityContainer unity) 15 { 16 InstanceProvider = new UnityInstanceProvider {Container = unity}; 17 } 18 19 public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) 20 { 21 //throw new NotImplementedException(); 22 } 23 24 public void ApplyDispatchBehavior(ServiceDescription serviceDescription,ServiceHostBase serviceHostBase) 25 { 26 foreach (ChannelDispatcherBase cdb 27 in serviceHostBase.ChannelDispatchers) 28 { 29 var cd= cdb as ChannelDispatcher; 30 if (cd != null) 31 { 32 foreach (EndpointDispatcher ed 33 in cd.Endpoints) 34 { 35 InstanceProvider.ServiceType= serviceDescription.ServiceType; 36 ed.DispatchRuntime.InstanceProvider = InstanceProvider; 37 38 } 39 } 40 } 41 }

Complete Sample can be downloaded from here

Introducing WCF Web API

Introduction

WCF is a highly sophisticated technology built on the foundation of replaceable transport. It is optimised for complex scenarios however only a handful of developers ever need to deal with those scenarios.

Most developers care a lot about the reach of the application and one of the best and easiest ways to do this is by supporting HTTP. WCF has always supported HTTP since its inception however the support was far from ideal because it could never take full advantage of HTTP.

HTTP is very well understood technology. Nearly every connected device available today supports one or other form of HTTP. If you speak the language of the Web, almost every consumer can consume your application.

WCF Web API fully implements HTTP Specification. It is important to note that WCF Web API is built on top of existing WCF and not replacing the existing WCF as we have come to know.

HTTP Support in WCF

HTTP Support has been part of WCF as part of various HTTP bindings, 3.5 SP1 made it easy to consume the response in XML and JSON. However it has never supported the features that make HTTP really powerful like full access to request and response, caching etc. HTTP is extremely flexible in the sense that it allows the body of the message to be presented in thousands of formats. WCF Web API allows this nicely by providing classes where you can provide support for any format over HTTP.

Architecture

clip_image002

Fig 1.0 Architecture Diagram

WCF Web API hooks into the extensibility mechanism of WCF. At the top layer it consists of resource class which consist of set of operation which receives HTTP Request and return HTTP Response.

Once the request is initiated from the client, WCF intercepts the request and start processing, it goes through its usual channel pipeline and once request is received in the form of bytes from the transport layer, it is converted from bytes to HttpRequestMessage.

After creation, the HttpRequestMessage instance passes through a sequence of message handlers. Each one of these message handlers receives an HttpRequestMessage and returns an HttpResponseMessage asynchronously.

After all the message handlers are processed, the operation is dispatched by first selecting the operation based on the request method name and Uri.

The next processing phase is responsible for producing the parameter set required by the selected operation, from the request message. These parameters are produced by operation handlers. These operation handlers may also be used to perform other type of operation specific message processing.

Before the operation is called, a resource class instance is obtained.

At the topmost layer, the operation is invoked using the parameters computed by the operation handlers.

After the operation’s invocation, the output parameters pass through a sequence of response operation handlers.

Also, if the response message was not returned by the operation, it is created in this phase.

Finally, the response message flows down through the message handlers until being turned into a byte sequence and written into the transport layer

Examples of Use of HTTP Verbs with WCF Web API

1. “GET” Example

This example takes a single parameter and returns fully typed HTTPResponseMessage of type person with the use of verb “GET”. Please note the use of HTTP natively and passing the Status Code in the standard HTTP format.

1 [WebGet(UriTemplate = "{id}")] 2 public HttpResponseMessage<Person> Get(int id) 3 { 4 5 var person = _repository.Get(id); 6 var response=new HttpResponseMessage<Person>(null); 7 if (person==null) 8 { 9 response.StatusCode = HttpStatusCode.NotFound; 10 } 11 else 12 { 13 response.Content = new ObjectContent<Person>(person); 14 } 15 return response; 16 }

2. “PUT” Example

This example takes two parameters and demonstrates how you can use “PUT”

1 [WebInvoke(UriTemplate = "{id}", Method = "PUT")] 2 public HttpResponseMessage<Person> Put(int id, Person person) 3 { 4 Get(id); 5 _repository.Update(person); 6 return new HttpResponseMessage<Person>(person); 7 }

3. GET with Queryable” Example

This example demonstrates OData style querying capabilities. More specifically you can retrieve records, apply filtering and also order them.

1 [WebGet(UriTemplate = "")] 2 public IQueryable<Person> Get() 3 { 4 return _repository.GetAll().AsQueryable(); 5 }

You can write queries In the format like

http://localhost/oData.Web/people?$filter=Id%20eq%201

Components of WCF Web API

WCF Web API is divided into following sections

1. Media Type Formatters

MediaTypeFormatters enables content negotiation. I.e. it makes it easier to support other format besides XML & JSON. If you want a resource to represent via specific format say iCal, just author a formatter and plug it in the pipeline. Following example shows how to represent a resource in a JpgFormatter.

1 public class JpgFormatter : MediaTypeFormatter 2 { 3 4 public JpgFormatter() 5 { 6 SupportedMediaTypes.Add(new MediaTypeHeaderValue("image/jpg")); 7 } 8 9 protected override bool OnCanReadType(Type type) 10 { 11 return true; 12 } 13 14 protected override bool OnCanWriteType(Type type) 15 { 16 return (type == typeof(Person)); 17 } 18 19 20 public override object OnReadFromStream(Type type, Stream stream, 21 HttpContentHeaders contentHeaders) 22 { 23 throw new NotImplementedException(); 24 } 25 26 public override void OnWriteToStream(Type type, object value, 27 Stream stream, HttpContentHeaders contentHeaders, 28 System.Net.TransportContext context) 29 { 30 var person = value as Person; 31 if (person != null) 32 { 33 { 34 var path = string.Format(CultureInfo.InvariantCulture, @"{0}bin\Images\Image{1}.jpg", 35 AppDomain.CurrentDomain.BaseDirectory, (Convert.ToInt32(person.Id) % 3) + 1); 36 using (var fileStream = new FileStream(path, FileMode.Open)) 37 { 38 var bytes = new byte[fileStream.Length]; 39 fileStream.Read(bytes, 0, (int)fileStream.Length); 40 stream.Write(bytes, 0, (int)fileStream.Length); 41 } 42 } 43 } 44 } 45 46 }

2. Message Handlers

WCF Web API provides low level message handlers as a mechanism to provide the hook into the HTTP Message Pipeline. You can do things like auditing of messages, provide security mechanisms etc. Following shows you an example of Logging Channel which hooks into the pipeline and then writes messages to trace.

1 public class LoggingChannel:DelegatingChannel 2 { 3 public LoggingChannel(HttpMessageChannel handler):base(handler) 4 { 5 } 6 7 protected override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, 8 System.Threading.CancellationToken cancellationToken) 9 { 10 System.Diagnostics.Trace.TraceInformation("Begin Request: {0} {1}", request.Method, request.RequestUri); 11 return base.SendAsync(request, cancellationToken); 12 } 13 }

 

3. Operation Handlers

Operation Handlers provides mechanism to intercept request before and after an operation is invoked. You can provide multiple operation handlers for the same operation. You can also provide Operation Handler for either single operation or all operation if required.

1 public class OperationHandlerFactory:HttpOperationHandlerFactory 2 { 3 4 5 protected override Collection<.HttpOperationHandler> OnCreateRequestHandlers(ServiceEndpoint endpoint, 6 HttpOperationDescription operation) 7 { 8 9 var baseHandlers = base.OnCreateRequestHandlers(endpoint, operation); 10 if (operation.InputParameters.Any(p => p.Type == typeof(int))) 11 { 12 baseHandlers.Add(new CustomRequestHandler(operation.InputParameters.FirstOrDefault().Name)); 13 } 14 15 baseHandlers.Add(new ZipOperationHandler(operation.InputParameters.FirstOrDefault().Name)); 16 baseHandlers.Insert(baseHandlers.Count() - 1, 17 new ZipOperationHandler(operation.InputParameters.FirstOrDefault().Name)); 18 19 return baseHandlers; 20 21 } 22 23 protected override Collection<HttpOperationHandler> OnCreateResponseHandlers(ServiceEndpoint endpoint, 24 HttpOperationDescription operation) 25 { 26 var baseHandlers = base.OnCreateRequestHandlers(endpoint, operation); 27 28 baseHandlers.Add(new ZipOperationHandler(operation.InputParameters.FirstOrDefault().Name)); 29 if (operation.Name.Contains("Get")) 30 { 31 baseHandlers.Add(new ZipOperationHandler(operation.InputParameters.FirstOrDefault().Name)); 32 } 33 34 return baseHandlers; 35 } 36 37 }

1 public class CustomRequestHandler:HttpOperationHandler<HttpRequestMessage,int> 2 { 3 public CustomRequestHandler(string outputParameterName) : base(outputParameterName) 4 { 5 } 6 7 public override int OnHandle(HttpRequestMessage input) 8 { 9 var stringValue=input.Content.ReadAsString(); 10 return 1; 11 } 12 }

4. Http Classes

WCF Web API provides two classes HttpRequestMessage and HttpResponseMessage for HTTP request and HTTP Response respectively.

5. HTTP Client

HTTP client can be used to connect REST based web services in a fully typed manner. You can use HttpClient to connect to web service, set headers, get fully typed response and work with the data instead of raw parsing. It supports Sync and Async methods to work with the resource.

1 const string address = "http://localhost/odata.web/people/"; 2 var client = new System.Net.Http.HttpClient(address); 3 4 //set which headers do you want 5 client.DefaultRequestHeaders.Accept 6 .Add(new MediaTypeWithQualityHeaderValue("text/json")); 7 8 var personQuery = client.CreateQuery<Person>(); 9 var results = personQuery.ExecuteAsync().ContinueWith(p => 10 { 11 foreach (var result in p.Result) 12 { 13 Console.WriteLine("Person Id:{0} and Name:{1}", result.Id, 14 result.Name); 15 } 16 17 }); 18

6. Queryability

WCF Web API supports OData style querying capabilities. In order to do this all you have to do is to create a method which return IQueryable<T>. Following shows you how simple it is to write a method and expose the method which supports OData style querying capabilities which includes ordering, filtering etc.

Once this is in place you can place request like http://localhost/Person?$filter=Id%20eq%201.It indicates “find me the person with an ID equal to 1”

7. Fluent Configuration

WCF API makes it easy to configure your application. It provides nice fluent style configuration where you can plug containers, handlers, MediaTypeFormatters and your resource classes.

1 protected void Application_Start(object sender, EventArgs e) 2 { 3 IUnityContainer container = new UnityContainer(); 4 container.RegisterType(typeof(PersonResource)); 5 container.RegisterType(typeof(PeopleResource)); 6 container.RegisterType( 7 typeof(IPersonRepository), typeof(PersonRespository), 8 new ContainerControlledLifetimeManager()); 9 10 var config = HttpHostConfiguration.Create() 11 .AddFormatters(new MediaTypeFormatter[] { new JpgFormatter() }) 12 .SetResourceFactory(new UnityFactory(container)) 13 .SetErrorHandler(new CustomErrorHandler()) 14 .AddMessageHandlers(typeof (LoggingChannel)); 15 16 RouteTable.Routes.MapServiceRoute<PersonResource>("person",config); 17 RouteTable.Routes.MapServiceRoute<PeopleResource>("people",config); 18 }

How to get bits.

Either get the bits from the Nuget package or download from http://wcf.codeplex.com.At the time of writing this article (May 2011), WCF Web API is in Preview 4. Although in a CTP stage, Microsoft has made a great start with WCF Web API. It not only allows us to create powerful applications by leverage support of HTTP but also made life of developers very easy by providing minimal effort to achieve this.

References

Glenn Block’s Blog

http://codebetter.com/glennblock/2011/05/15/using-datacontracts-with-wcf-web-api/

Daniel Cazzulino’s Blog

http://blogs.clariusconsulting.net/kzu/

Multiple WCF Services on a single port

One of the more common problems most WCF developers have is to make multiple service hosted on windows service (or console service for that matter) and the common misconception is that Service Host can only listen to one port. Well that may partly be true but you can definitely take advantage of addressing mechanism in order to overcome this.

e.g You have two service PersonService where service contract is IPersonService and another one as AccountingService whose service contract is IAccountingService.

You can host both of them on a windows service host but can share single port if you re-arrange the addressing scheme in this way http://localhost:6962/IAccountingService/ and http://localhost:6962/IPersonService/ .You may be wondering what is new in this since all of us have been doing this in IIS since the beginning. The difference between IIS is that when you use .svc files, it kinds of forces you to choose multiple host files so above addressing becomes like http://localhost:6962/AccountingService.svc and http://localhost:6962/PersonService.svc.

To make it easy to host multiple service share single port without separate host files, I have created this helper class called MultipleServiceHost however it does not inherit from ServiceHost. You can use the same mechanism in either console application or windows service as it support starting, stopping and restarting methods.

StartServices method describes the behavior, it is basically appending the contract name of the WCF service in the address so that multiple service can share the same port.

1 public void StartServices() 2 { 3 _serviceHosts.Clear(); 4 5 foreach (var type in _mappings) 6 { 7 Type contractType = type.Key; 8 Type implementationType = type.Value; 9 10 var serviceHost = new ServiceHost(implementationType); 11 var endpoint = serviceHost.AddServiceEndpoint(contractType, 12 _binding,_baseUrl + "/" + contractType.Name); 13 14 var metadataBehavior = new ServiceMetadataBehavior(); 15 16 serviceHost.Description.Behaviors.Add(metadataBehavior); 17 serviceHost.AddServiceEndpoint(typeof(IMetadataExchange), 18 MetadataExchangeBindings.CreateMexHttpBinding(), 19 _baseUrl + "/" + contractType.Name + "/MEX"); 20 21 var serviceDebugBehaviour = 22 serviceHost.Description.Behaviors.Find<ServiceDebugBehavior>(); 23 serviceDebugBehaviour.IncludeExceptionDetailInFaults = true; 24 25 Console.WriteLine("Service is running at"+ endpoint.Address); 26 27 serviceHost.Open(); 28 serviceHost.Faulted += new EventHandler(ServiceHostFaulted); 29 _serviceHosts.Add(serviceHost); 30 } 31 32 }

Constructor code

1 public class MultipleServiceHost 2 { 3 private readonly Dictionary<Type,Type> _mappings= 4 new Dictionary<Type, Type>(); 5 private readonly Binding _binding; 6 private readonly string _baseUrl; 7 8 public MultipleServiceHost(Dictionary<Type, Type> mappings, 9 string baseUrl, Binding binding) 10 { 11 _mappings = mappings; 12 _baseUrl = baseUrl; 13 _binding = binding; 14 } 15 16 private readonly List<ServiceHost> _serviceHosts = 17 new List<ServiceHost>();

Caller Code:

1 static void Main(string[] args) 2 { 3 var mappings = new Dictionary<Type, Type> 4 { 5 {typeof (IAccountingService), typeof (AccountingService)}, 6 {typeof(IPersonService), typeof(PersonService)} 7 }; 8 9 var multipleServiceHost = new MultipleServiceHost(mappings, "http://localhost:6962", GetDefaultBinding()); 10 multipleServiceHost.StartServices(); 11 12 Console.WriteLine("Services are running,press any key to stop services"); 13 Console.ReadKey(); 14 multipleServiceHost.StopServices(); 15 16 //multipleServiceHost.RestartServices(); 17 //Console.WriteLine("Services are running,press any key to stop services"); 18 //Console.ReadKey(); 19 //multipleServiceHost.StopServices(); 20 21 } 22 23 public static Binding GetDefaultBinding() 24 { 25 return new BasicHttpBinding(); 26 } 27

Complete Sample can be found here