Monday, 13 May 2013

Creating an assembly aware DataContractResolver in WCF

If you have coded some in WCF, you will sooner or later have experienced the issue where you want to derive a data contract and create a WCF service with an operation that returns a base class, but the WCF service in fact can return derived classes. In any case, when you use inheritance with data contracts, there are issues around the serialization and deserialization. The solution for now has been to decorate the base class with the KnownTypeAttribute of all the derived classes that should be supported. Clearly, this strategy only works in the simplest scenarios and sooner or later you will have runtime exceptions while serializing and deserializing as the WCF service operations execute. A solution to this, is to create a custom DataContractResolver. This custom object will inherit from the DataContractResolver and customize the serialization and deserialization process. For this to work, you will have to set the DataContractResolver on WCF operations and make the necessary adjustments both on the serverside and the clientside. I have created a custom ServiceHostFactory that sets the DataContractResolver for all WCF operations for all endpoints. For some scenarios, this is not desired, but the source code shows how we can globally apply this DataContractResolver to all WCF operations. The ServiceHostFactory is called WebEnabledServiceHostFactory and looks like this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Description;
using System.Web;

namespace TestServiceHostFactory.IIS
{

    public class WebEnabledServiceHostFactory : ServiceHostFactory
    {

        private static readonly object _locker = new object(); 

        private static Dictionary _serviceLookup = new Dictionary();

        private static readonly string _dataContractAssemblyName = "Types";

        private static Assembly _dataContractAssembly;

        private static AssemblyAwareDataContractResolver _dataContractResolver;

        static WebEnabledServiceHostFactory()
        {
            lock (_locker)
            {
                _serviceLookup.Add(typeof(ICalculatorService), typeof(CalculatorService));
                _serviceLookup.Add(typeof(ICustomerService), typeof(CustomerService)); 
            }
        }

        protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
        {
            ServiceHost host = new ServiceHost(_serviceLookup[serviceType], baseAddresses);

            ServiceEndpoint endpoint = host.AddServiceEndpoint(serviceType, new WebHttpBinding(), "web");
            ServiceEndpoint endpointWs = host.AddServiceEndpoint(serviceType, new WSHttpBinding(), "ws"); 

            endpoint.EndpointBehaviors.Add(new WebHttpBehavior());

            ServiceMetadataBehavior smb = new ServiceMetadataBehavior { HttpGetEnabled = true };
            host.Description.Behaviors.Add(smb);

            foreach (ServiceEndpoint serviceEndpoint in host.Description.Endpoints)
            {
                foreach (OperationDescription operation in serviceEndpoint.Contract.Operations)
                {
                    DataContractSerializerOperationBehavior serializerBehavior = operation.OperationBehaviors
                        .OfType<DataContractSerializerOperationBehavior>().FirstOrDefault();
                    
                    if (serializerBehavior == null)
                    {
                        serializerBehavior = new DataContractSerializerOperationBehavior(operation);
                        operation.OperationBehaviors.Add(serializerBehavior); 
                    }

                    if (_dataContractAssembly == null)
                        _dataContractAssembly = Assembly.Load(_dataContractAssemblyName);

                    if (_dataContractResolver == null)
                        _dataContractResolver = new AssemblyAwareDataContractResolver(_dataContractAssembly); 
                   
                    serializerBehavior.DataContractResolver = _dataContractResolver;

                }
            }

            return host;
        }

    }

}

This WCF ServiceHostFactory derived class both supports web operations and sets a custom DataContractResolver, AssemblyAwareDataContractResolver. This data contract resolver is assembly aware, i.e. it can traverse an assembly, look for all types (classes), decorated with the DataContract attribute, signifying that this class is a data contract. As you can see in the ServiceHostFactory code above, we loop through all the WCF endpoints, then loop through all the operations (OperationDescription) inside the Contract property of the Endpoint, next we look at the OperationBehaviors if there is already added a DataContractSerializerOperationBehavior and if not, we add such an object. We finally specify the DataContractResolver of this behavior which we set to our custom AssemblyAwareDataContractResolver. Note that we add the assembly in the constructor to this object. We know in this special case that the assembly is in the Types project. An alternative would be to expose a public property for example to set the name of the assembly (i.e. project), where the assembly resides. Another alternative would be to support multiple assemblies where data contracts will reside. For most cases, most developers has got their data contracts set up in a Common project and assembly, along with Service Contracts. Let's look at the source code of AssemblyAwareDataContractResolver next:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Web;
using System.Xml;
using System.Collections.Concurrent;
using System.Text;
using System.Diagnostics;
using System.IO;

namespace TestServiceHostFactory.IIS
{

    public class AssemblyAwareDataContractResolver : DataContractResolver
    {

        private ConcurrentDictionary dictionary = new ConcurrentDictionary(); 

        private Assembly assembly;

        public AssemblyAwareDataContractResolver(Assembly assembly)
        {
            this.assembly = assembly;
            FamiliarizeWithDataContracts(assembly); 
        }

        private void FamiliarizeWithDataContracts(Assembly assembly)
        {
            DataContractSerializer serializer = new DataContractSerializer(typeof(Object), null, int.MaxValue, false, true, null,
                       this);
            StringBuilder stringBuilder = new StringBuilder();

            foreach (Type type in assembly.GetTypes())
            {
                SerializeDataType(serializer, stringBuilder, type);
            }

            //foreach (Type type in assembly.GetTypes())
            //{
            //    SerializeDataType(serializer, stringBuilder, type);
            //    DeserializeDataType(serializer, stringBuilder);

            //}
        }


        //private static void DeserializeDataType(DataContractSerializer serializer, StringBuilder stringBuilder)
        //{
        //    string serialized = stringBuilder.ToString();

        //    using (XmlReader xmlReader = XmlReader.Create(new StringReader(serialized)))
        //    {
        //        object deSerialized = serializer.ReadObject(xmlReader);
        //    }
        //}


        private static void SerializeDataType(DataContractSerializer serializer, StringBuilder stringBuilder, Type type)
        {
            if (type.GetCustomAttributes().Count() > 0)
            {
                var dataContract = Activator.CreateInstance(type);
                using (XmlWriter xmlWriter = XmlWriter.Create(stringBuilder))
                {
                    try
                    {
                        serializer.WriteObject(xmlWriter, dataContract);
                    }
                    catch (SerializationException se)
                    {
                        Debug.WriteLine(se.Message);
                    }
                }

                Debug.WriteLine(stringBuilder.ToString());

            }
        }

        /// 
        /// Serialization will use this overload
        /// 
        public override bool TryResolveType(Type type, Type declaredType, DataContractResolver knownTypeResolver, out XmlDictionaryString typeName, out XmlDictionaryString typeNamespace)
        {
            string name = type.Name;
            string namesp = type.Namespace;

            typeName = new XmlDictionaryString(XmlDictionary.Empty, name, 0);
            typeNamespace = new XmlDictionaryString(XmlDictionary.Empty, namesp, 0);

            if (!dictionary.ContainsKey(type.Name))
                dictionary.TryAdd(name, typeName);

            if (!dictionary.ContainsKey(type.Namespace))
                dictionary.TryAdd(namesp, typeNamespace);

            return true;
        }

        /// 
        /// Deserialization will use this overload 
        /// 
        public override Type ResolveName(string typeName, string typeNamespace, Type declaredType, DataContractResolver knownTypeResolver)
        {
            XmlDictionaryString tName;
            XmlDictionaryString tNamespace;

            if (dictionary.TryGetValue(typeName, out tName) && dictionary.TryGetValue(typeNamespace, out tNamespace))
                return this.assembly.GetType(tNamespace.Value + "." + tName.Value);
            else
                return null;         
        }

    }
}

Make note that we familiarize the AssemblyAwareDataContractResolver by looping through all types and serialize them (default types and classes), using Activator.CreateInstance and serialize the object. This is done to set up a dictionary data structure (from the Concurrent assembly). Of course, this will have some overhead, which is why we use the same AssemblyAwareDataContractResolver instance in the ServiceHostFactory for quick serialization and deserialization, once inited. You can also see that we derive from the DataContractResolver class and override ResolveName (used during deserialization) and TryResolveType (used during serialization). Next, we need some service to test out WCF with these new capabilities. Lets first look at the data contracts involved in the Types project (class library):

using System.Runtime.Serialization;


namespace Types
{

    [DataContract]
    public class Customer
    {

        [DataMember]
        public string Name { get; set; }
    
    }

    [DataContract]
    public class RegularCustomer : Customer
    {

    }

    [DataContract]
    public class VIPCustomer : Customer
    {

        [DataMember]
        public string VipInfo { get; set; }

        [DataMember]
        public Customer Attache { get; set; }
    }

    [DataContract]
    public class PreferredVIPCustomer : VIPCustomer
    {

    }

}


Make note we have inheritance here of our data contracts, and that we have not set the KnownType attribute on the base class for the derived classes. After all, we want our WCF service to be assembly aware, right? Let's define a service contract next. This resides in the WCF service application, but should be moved to the Types project.

using System.ServiceModel;
using System.ServiceModel.Web;
using Types;

namespace TestServiceHostFactory.IIS
{

    [ServiceContract(Namespace = "http://www.foo.bar.com")]
    public interface ICustomerService
    {

        [OperationContract]
        [WebGet] 
        Customer GetCustomer(string name);

    }

}

The implementation is in the same project, CustomerService:

using Types;

namespace TestServiceHostFactory.IIS
{

    public class CustomerService : ICustomerService
    {

        public Customer GetCustomer(string name)
        {
            if (!name.Contains("VIP"))
                return new Customer { Name = name };
            else
            {
                var result = new VIPCustomer { Name = name, VipInfo = "VIP: " + name, Attache = new Customer { Name = "Geoffrey" } };
                return result;
            }
        }

    }

}

We also need a Customer.svc file to expose our service:

<% @ ServiceHost Language="C#" Service="TestServiceHostFactory.IIS.ICustomerService" Factory="TestServiceHostFactory.IIS.WebEnabledServiceHostFactory" %>

The <system.serviceModel> section of the web config file in this example is empty, as the complexity of setting up endpoints and behaviors are taken care of in the custom service host. The next step is to connect to this WCF CustomerService and check that the automatic resolution of inheritance in the data contracts of the assembly Types is taken care of with our custom (AssemblyAware)DataContractResolver. I have created a simple console project with a main method inside where I put the client initialization code and the set up a channel factory to communicate with the service. I know the endpoint to go against.

using System;
using System.Linq;
using System.Reflection;
using System.ServiceModel;
using System.ServiceModel.Description;
using TestServiceHostFactory.IIS;

namespace TestServiceHostFactory.Client
{
    class Program
    {
        static void Main(string[] args)
        {

            WSHttpBinding binding = new WSHttpBinding();
            EndpointAddress endpoint = new EndpointAddress("http://localhost:51229/Customer.svc/ws");

            ChannelFactory customerService = new ChannelFactory(binding, endpoint);

            Assembly dataContractAssembly = Assembly.Load("Types");

            foreach (var operationDescription in customerService.Endpoint.Contract.Operations)
            {
                var serializerBehavior = operationDescription.OperationBehaviors.OfType<DataContractSerializerOperationBehavior>().FirstOrDefault();
                if (serializerBehavior == null)
                {
                    serializerBehavior = new DataContractSerializerOperationBehavior(operationDescription);
                    operationDescription.OperationBehaviors.Add(serializerBehavior);
                }
                serializerBehavior.DataContractResolver = new AssemblyAwareDataContractResolver(dataContractAssembly);
            }

            ICustomerService c = customerService.CreateChannel();

            var cust = c.GetCustomer("VIP Tore Aurstad");

            Console.WriteLine("Press any key to continue ...");
            Console.ReadKey();
        }

    }
}

I set up a binding instance of type WsHttpBinding (since this must match the .AddServiceEndPoint calls defined on the ServiceHost on the server side, which is performed inside the WebEnabledServiceHostFactory), and create an Endpoint with an address, which matches the address set up of the Service Application project set up. To see this url, choose a WCF service application project, right click and select properties and click on the Web tab pane and look at the Project Url, where the port number should be described. I create a new ChannelFactory to go against the ICustomerService WCF service (interface). Also note that the client side must have set up its corresponding AssemblyAwareDataContractResolver. You will want to reuse the same object for and not instantiate it as I have done here, for efficiency reasons, after all - remember the FamiliarizeWithDataContract call. For this demonstration, I have not done this optimization. We then use the CreateChannel method of the ChannelFactory and create the connection between the client and the server. Now we can call the WCF operation GetCustomer. We pass in the string "VIP Tore Aurstad", and if you look at the logic, this will return a VIPCustomer object. This is a derived class of the Customer data contract type. Although we have not specified KnownType attribute, we still avoid runtime crash, since our DataContractResolver is now assembly aware. To sum up, from .NET Framework version 4.0, WCF offers you to take control of how DataContracts are resolved during serialization and deserialization. If you have a project (class library) with many data contracts, you should consider using a class hierarchy to reduce the number of classes used for data contracts. Many developers avoid inheritance in data contracts that are used with WCF, because of the costs around maintaining the KnownType attributes. In fact, many developers are not sure what to do when they encounter these runtime exceptions in the first place. By taking your time to implement an assembly aware DataContractResolver, you are reducing a maintenance cost around adding KnownType to your data contracts. Of course, this means you must have an efficient implementation of this. Note what I said about the client code needs to keep a reference to the instance of AssemblyAwareDataContractResolver when you loop through endpoints and operations. For this simple implementation, this issue did not matter. It is expected that the FamiliarizeWithDataContract method is quick enough, but you should consider parallelizing it further to register the serializing data ccontracts. If you extract the client code above into a ChannelManager or similar, you can cache this object into a static variable, such that the overhead is mminimal. This cost compared to the reduced maintenance cost of inheritance and KnownType should be worth the effort. In addition, by better supporting inheritance with data contracts, you should be able to design better class hierarchies for your data contracts and implement DRY in your data contracts.

Sunday, 12 May 2013

Creating a web enabled service via ServiceHostfactory in WCF

This article will explain how a service host factory can create a webenabled service in WCF. Obviously, you should consider extending this ServiceHostFactory to consider security and other extensions to it. Start by creating a WCF Service Application in Visual Studio. Add references to System.ServiceModel, System.ServiceModel.Web and System.ServiceModel.Activation. Let's first look at the ServiceHostFactory class itself:

    public class WebEnabledServiceHostFactory : ServiceHostFactory
    {

        private static readonly object locker = new object(); 

        private static Dictionary serviceLookup = new Dictionary();

        static WebEnabledServiceHostFactory()
        {
            lock (locker){
             serviceLookup.Add(typeof(ICalculatorService), typeof(CalculatorService));
            }
        }

        protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
        {
            ServiceHost host = new ServiceHost(serviceLookup[serviceType], baseAddresses);

            ServiceEndpoint endpoint = host.AddServiceEndpoint(serviceType, new WebHttpBinding(), "web");

            endpoint.EndpointBehaviors.Add(new WebHttpBehavior());

            ServiceMetadataBehavior smb = new ServiceMetadataBehavior { HttpGetEnabled = true };
            host.Description.Behaviors.Add(smb);

            return host;
        }

    }

This ServiceHostFactory class derived from the base class ServiceHostFactory. It just overrides the CreateServiceHost method and adds a service endpoint with the AddServiceEndPoint method of ServiceHost and uses the WebHttpBinding. A ServiceEndPoint instance is returned by this method and we add the WebHttpBehavior to the endpoint. In addition, we add a ServiceMetdataBehavior to the host.Description.Behaviors property of the ServiceHost with HttpGetEnabled set to true, so we get the familiar testpage of the .svc file in a web browser. Note that we use a simple static dictionary for reading the mapping between the service contract and its implementation class. Let's then add a simple service contract:

    [ServiceContract(Namespace = "http://www.foo.bar.com")]
    public interface ICalculatorService
    {

        [OperationContract]
        [WebGet]
        double Subtract(double x, double y);

        [OperationContract]
        [WebGet] 
        double Add(double x, double y);

    }

Note that we not only have specified the method of the ServiceContract as using OperationContract, but we also decorate the method with the WebGet attribute to support WCF Web programming model (i.e. consuming the WCF Service via HTTP + Web browser) The WCF implementation of this interface and WCF service contract is done next:

    public class CalculatorService : ICalculatorService
    {
        public double Subtract(double x, double y)
        {
            return x - y;
        }

        public double Add(double x, double y)
        {
            return x + y;
        }
    }

Add a svc file called Calculator.svc next, specifying the calculator service and the custom ServiceHostFactory above:

<% @ ServiceHost Language="C#" Service="TestServiceHostFactory.IIS.CalculatorService" Factory="TestServiceHostFactory.IIS.WebEnabledServiceHostFactory" %>

Note that the endpoint in the service host defines the end point with an address of "web", when we right click the Calculator.svc file the file is opened in a web browser with a generated address, with a random port assigned. When I right click the Calculator.svc file, the following URL was used in this example: http://localhost:51229/Calculator.svc To for example call the Subtract method of the ICalculatorService, we use the following URL in the web browser: http://localhost:51229/Calculator.svc/web/Subtract?x=12&y=3 This returns the following result: <double>9<double> In case JSON is the desired ResponseFormat, just change the signature of the ServiceContract classes to specify this, for example:
        [OperationContract]
        [WebGet(ResponseFormat=WebMessageFormat.Json)]
        double Subtract(double x, double y);
In this example, the result will just the number 9. If objects are returned, JSON object syntax will be returned. Our web.config has an empty block for <system.serviceModel>
 <system.serviceModel>
 </system.serviceModel>
This shows that we can auto-configure web services as desired in for multiple WCF services using a ServiceHostFactory and setting up bindings and behaviors out-of-the box. This reduces complexity and configuration that has to go into web.config and the <system.serviceModel> section, which specifies WCF. In addition, if you want to add WCF services that are web-enabled out-of-the box, the code above can be a starting point.

Sunday, 5 May 2013

Accessing WCF service that is REST-enabled in a web browser

Developers using WCF most often will expose and consume these services in intranet business applications. But sometimes, it is desired to expose services through a web browser.

To expose a WCF service to a web browser, it is possible to do this using the WCF web programming model, based upon the ideas of REST (Representational State Transfer). This article will show how this can be achieved in WCF, using some easy adjustments. Make note that it is possible to allow both a traditional access and web based access, it boils down to activating and adding the necessary endpoints.

First off, let us take the default WCF Service Library template as a starter point.


    public class Service1 : IService1
    {

        [WebGet(UriTemplate="GetData?value={value}")] 
        public string GetData(int value)
        {
            return string.Format("You entered: {0}", value);
        }

        ..

    }

The difference between the code above and the one in the template, is that the service method implementation class Service1 is attributed with the WebGet attribute. In addition, an UriTemplate is added. The WebGet attribute is used to support HTTP GET operations. To use the POST, PUT or DELETE operation in HTTP, use the HttpInvoke attribute. To be able to use this WCF HTTP Programming model you not only have to add a reference to the System.ServiceModel assembly, but also System.ServiceModel.Web assembly. In addition, add the following using statement:
using System.ServiceModel.Web;
Next, some changes must be done in the configuration files for the project where WCF service is located. Open the web.config (or app.config) of the project containing the WCF service. Check that you have the following in the system.servicemodel section:

<system.serviceModel>
    <services>
      <service name="HelloWorldWCFService.Service1">
        <host>
          <baseAddresses>
            <add baseAddress = "http://localhost:8734/Service1/" />
          </baseAddresses>
        </host>
        <!-- Service Endpoints -->
        <!-- Unless fully qualified, address is relative to base address supplied above -->
        <endpoint address="" binding="basicHttpBinding" contract="HelloWorldWCFService.IService1">
          <!-- 
              Upon deployment, the following identity element should be removed or replaced to reflect the 
              identity under which the deployed service runs.  If removed, WCF will infer an appropriate identity 
              automatically.
          -->
          <identity>
            <dns value="localhost"/>
          </identity>
        </endpoint>
        <endpoint address="http://localhost:8733/Service1/mex" binding="mexHttpBinding" contract="IMetadataExchange"  /> 
        <endpoint address="net.tcp://localhost:8080/Service1" binding="netTcpBinding" contract="HelloWorldWCFService.IService1" />
       
        <endpoint address="http://localhost:8734/Service1/Web/" binding="webHttpBinding" contract="HelloWorldWCFService.IService1" behaviorConfiguration="webBehaviorConfig" />
        
        <!-- Metadata Endpoints -->
        <!-- The Metadata Exchange endpoint is used by the service to describe itself to clients. --> 
        <!-- This endpoint does not use a secure binding and should be secured or removed before deployment -->
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
        
       
      </service>
    </services>
    <behaviors>
      <endpointBehaviors>
        <behavior name="webBehaviorConfig">
          <webHttp />
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>

        <behavior>
          <!-- To avoid disclosing metadata information, 
          set the values below to false before deployment -->
          <serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/>
          <!-- To receive exception details in faults for debugging purposes, 
          set the value below to true.  Set to false before deployment 
          to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="False" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>


That was a lot of config. In fact what is key to note here is just that we add an endpoint that has the webHttpBinding endpoint. The address is the URL that will be used to access the service, as the prefix combined with the UriTemplate of each WCF operation that is exposed. In addition, the endpointBehaviors element is added with a behavior where we give it a name and add the webHttp element. Also, note that the attributes httpGetEnabled and httpsGetEnabled is set on the serviceMetadata element. To access the web-enabled WCF service in this example, open a web browser and enter the following URL:
http://localhost:8734/Service1/Web/GetData?value=42


The returned data is in the form of an XML, which is the default output format. It is possible to change the output format into JSON for example, to integrate the data returned with Javascript and Ajax in modern web browsers.
This will give you a start to test out accessing the WCF service through a web browser. Of course, when exposing WCF service on the web, security considerations should be taken. Most often, it comes down to what should be done when a new attack vector is made available. Obviously, more often than not, you will want to limit which users can access the web service. In addition, the service should not expose sensitive data, without security considerations. There are also limits in which data can be passed in an URL. When you use the WebInvoke attribute, more complex objects can be passed into a service, but still, the object being passed in must be serializable into an XML.

Also note that the UriTemplate must match the naming of the parameters to the WCF method. There are limitations to which data types can be passed in a query string. An explanation of the format one must follow when it is required to pass, say a DateTime, check out the following MSDN article:
WCF Web HTTP Programming Model Overview

It is easy to change the output from XML to JSON.

We will now look at calling the same WCF Method used above through jQuery and its $.ajax method. First, change the signature of the WCF service:
        [WebInvoke(ResponseFormat=WebMessageFormat.Json, BodyStyle=WebMessageBodyStyle.Wrapped)] 
        public string GetData(int value)
        {
            return string.Format("You entered: {0}", value);
        }
Note that we do not specify the Method property of WebInvoke, which defaults to POST verb of HTTP. We have also changed from WebGet to WebInvoke. Next, adding a MVC 4 application to act as a client, add the following code to your global.asax code behind file (Global.asax.cs) in this project:
     
        protected void Application_BeginRequest(object sender, EventArgs e)
        {

            HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "http://localhost:*/");

            if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
            {
                HttpContext.Current.Response.AddHeader("Cache-Control", "no-cache");
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST");
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
                HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
                HttpContext.Current.Response.End();
            }
        }

The code above is to added to fix compability issues in Chrome and Firefox to allow Ajax calls to the WCF service (IE did not need this fix). Add the following content to the Index.cshtml file of the added MVC Project:
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js"></script>

    <script type="text/javascript">

        function testPosting() {

            jQuery.support.cors = true;

            var enteredValue = $("#txtValue").val();
            var data = { value: enteredValue };

            var payload = JSON.stringify(data);

            $.ajax({
                type: 'POST',
                url: 'http://localhost:8734/Service1/Web/GetData',
                contentType: 'application/json',
                dataType: 'text',
                data: payload,
                error: function (request, status, error) {
                    alert(request.responseText + " " + status + " " + error);
                },
                success: function (msg) {
                    var result = JSON.parse(msg);
                    console.log(result);
                    $("#results").append(result.GetDataResult + "<br />");
                }
            });

        }

    </script> 
Adding jquery above is not necessary, since the MVC template has already added this. Next, a method called testPosting is added. Here, a call to the $.ajax method is added. The $.ajax metod specifies the url of the WCF service. Also note that the service should be on the same server and preferably the same port to avoid security issues. Of course, your service can access remote servers in its code. This means that the Web Application and the WCF Service preferably should be installed on the same server. Cross-domain scripts are usually disallowed in web browsers today. But the option for your WCF services to access remote servers is of course not affected by this limitation. The dataType is set to 'text', but it could be 'json'. Instead, the json is parsed in the success callback. Further on, the name of the argument of your WCF method must match the constructed json object being passed into the method.


We need a simple GUI also to test the combination of WCF, REST, Ajax and JSON (GUI below is just a mockup in Google Blogger):
 

Enter an integer:



The code in the Global.asax.cs file was obtained by reading this article: Method 405 fix for WCF

This shows that WCF services can provide XML, JSON, Ajax and REST capabilities and not just be an intranet web services provider, as its typical use. Of course, often WCF will feel a bit heavy weight when all you want is to expose web services to your Clients. But again, often you want to create Intranet style web applications too, where you want some of your services and their methods provide web access. This will make it easier to use existing WCF services hosted in IIS through for example WAS to be utilized by mobile clients. The information which these methods of your WCF services will usually be services that are not sensitive, or else one has to provide security mechanisms around the web access. One possible way of adding security is to provide a token or similar information in the JSON payload being sent over to the server. If the WCF service verfies the token sent in, the information will then be sent back again to the client. For example, the client could log in to a web application which uses a Security Token Service or similar to log in. If WIF is used, the client will get a FedAuthCookie as a certification of a valid user. The user can then relay the necessary information over to the WCF Rest-enabled service to inspect the users claims or similar. One could use a digital signature or similar. I will look at WCF REST security tokens and related topics in the near future. The level of security will be lower than what is possible in many other types of bindings being used in WCF such as wsFederationBinding or similar.

This article shows that WCF can be used in many web scenarios. I have not touched the topics of WebServiceHost and calling the REST-enabled services through code and not JavaScript. If you want a web-enabled WCF service, chances are higher that you want to reach the WCF service through jQuery + Ajax or similar using JSON as information interchange format. There are a multitude of topics to cover here and the developer should be aware that it is a learning curve to start using WCF for the web.