Search code examples
wcfserviceendpointbehaviorwebhttp

WCF WebHttp, Service, Behaviors, Endpoints, Custom Formatter


I followed this guide for creating my custom formatter so I could use the Newtonsoft Json.NET for object serialization since the built in Microsoft one doesn't support cycles from parent/child relationships.

http://blogs.msdn.com/b/carlosfigueira/archive/2011/05/03/wcf-extensibility-message-formatters.aspx

In his example he's manually creating his ServiceHost. I am leveraging Routes and the WebServiceFactory taught to me by this guide.

http://blogs.msdn.com/b/endpoint/archive/2010/01/06/introducing-wcf-webhttp-services-in-net-4.aspx

From what I can tell I just need to figure out a way to add the appropriate Behaviour to my Service endpoints. Any help in pointing me in the right direction would be appreciated.

Some code snippets below for ease of reference...


In my Global.asax

        WebServiceHostFactory webServiceHostFactory = new WebServiceHostFactory();
        RouteTable.Routes.Add(new ServiceRoute(Accounts.Route, webServiceHostFactory, typeof(Accounts)));

If my web.config

<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
<standardEndpoints>
    <webHttpEndpoint>
    <!-- 
        Configure the WCF REST service base address via the global.asax.cs file and the default endpoint 
        via the attributes on the <standardEndpoint> element below
    -->
    <standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="false" defaultOutgoingResponseFormat="Json"/>
    </webHttpEndpoint>
</standardEndpoints>

In the Main function of his program

        string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
        ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
        host.AddServiceEndpoint(typeof(ITestService), new BasicHttpBinding(), "soap");
        WebHttpBinding webBinding = new WebHttpBinding();
        webBinding.ContentTypeMapper = new MyRawMapper();
        host.AddServiceEndpoint(typeof(ITestService), webBinding, "json").Behaviors.Add(new NewtonsoftJsonBehavior());

Solution

  • To use the routes and get a reference to the service endpoint, you'll need your custom service host factory. It can do the same as the WebServiceHostFactory which you're currently using (simply return a reference to the WebServiceHost), but instead return a reference to your custom service host.

    You can find more information about service host factories at http://blogs.msdn.com/b/carlosfigueira/archive/2011/06/14/wcf-extensibility-servicehostfactory.aspx.

    public class MyServiceHostFactory : ServiceHostFactory
    {
        protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
        {
            return base.CreateServiceHost(serviceType, baseAddresses);
        }
    
        class MyServiceHost : WebServiceHost
        {
            public MyServiceHost(Type serviceType, Uri[] baseAddresses)
                : base(serviceType, baseAddresses)
            { }
    
            protected override void OnOpening()
            {
                base.OnOpening();
    
                foreach (ServiceEndpoint endpoint in this.Description.Endpoints)
                {
                    CustomBinding custom = endpoint.Binding as CustomBinding;
                    if (custom != null)
                    {
                        custom = new CustomBinding(endpoint.Binding);
                    }
    
                    custom.Elements.Find<WebMessageEncodingBindingElement>().ContentTypeMapper = new MyRawMapper();
                    endpoint.Binding = custom;
    
                    endpoint.Behaviors.Add(new NewtonsoftJsonBehavior());
                }
            }
        }
    }