Welcome to Ultra Developers.

the company that developes your success

Read Blog


How to: Return a specific Http Status Code from WCF REST Service

How to: Return a specific Http Status Code from WCF REST Service

When you create a WCF REST Service, the caller of the service wants you to return specific HTTP Status Codes for specific situations such as where there is no data to return in a search query he want to return HTTP 204 No Content. In this article we will show you how to create a WCF REST Service and how to return some common HTTP Status Codes from your service.

Create a WCF REST Service

  1. Open Visual Studio 2010.
  2. Click on New Project from the Start Page of Visual Studio. The New Project dialog appears.
  3. From the left pane select C# and then WCF Templates.
  4. From the right pane select WCF service Library.
  5. Type your WcfRestService in the name and then click Ok.

WcfRestService

  1. The project is created and contains one interface IService1.cs (our contract) and a class Service1.cs (our service).

WcfRestService

  1. In solution Explorer, right click the IService.cs file and click rename. Type ICustomer.cs as the contract name.
  2. You will be asked if you want to rename the interface, select Yes.

WcfRestService

  1. In solution Explorer, right click the Service.cs file and click rename. Type Customer.cs as the service name.
  2. You will be asked if you want to rename the service name select Yes.

WcfRestService

  1. Right click the WcfRestService project and select properties. You will find that the service runs under the .Net Framework 4 Client Profile.
  2. Change Target framework to be .Net Framework 4.

WcfRestService

  1. Right click the WcfRestService project and select Add Reference. The Add Reference Dialog appears.
  2. Find the System.ServiceModel.Web in the .NET tab and click OK.

WcfRestService

Add & configure CustomerInfo Data Contract

  1. From Solution Explorer, right click WcfRestService project. Select Add then New Item...
  2. The Add New Item Dialog appears.
  3. From the left pane select C# and then Code.
  4. From the right pane select class.
  5. Type CustomerInfo.cs as the name of the new class. This class will work as our data contract that we will hold our customers data.

WcfRestService

  1. Add a reference to the following namespace using the following using statements
using System.Runtime.Serialization;
  1. The System.Runtime.Serialization namespace contains classes that can be used for serializing and deserializing objects. Serialization is the process of converting an object or a graph of objects into a linear sequence of bytes for either storage or transmission to another location. Deserialization is the process of taking in stored information and recreating objects from it.
  2. Add the following code to the CustomerInfo class
[DataContract]
public class CustomerInfo
{
    private int customerId;
    private string customerName, address, mobile, phone, email;
    private DateTime birthdate;

    [DataMember]
    public int CustomerId
    {
        get
        {
            return customerId;
        }
        set
        {
            customerId = value;
        }
    }

    [DataMember]
    public stringCustomerName
    {
        get
        {
            return customerName;
        }
        set
        {
            customerName = value;
        }
    }

    [DataMember]
    public string Address
    {
        get
        {
            return address;
        }
        set
        {
            address = value;
        }
    }

    [DataMember]
    public string Mobile
    {
        get
        {
            return mobile;
        }
        set
        {
            mobile = value;
        }
    }

    [DataMember]
    public string Phone
    {
        get
        {
            return phone;
        }
        set
        {
            phone = value;
        }
    }

    [DataMember]
    public string Email
    {
        get
        {
            return email;
        }
        set
        {
            email = value;
        }
    }

    [DataMember]
    public DateTimeBirthdate
    {
        get
        {
            return birthdate;
        }
        set
        {
            birthdate = value;
        }
    }
}
  1. In The above code:
    • We simply marks the CustomerInfo class with the DataContract Attribute.
    • Then adds an integer variable customerId, and 5 string variable, and a DateTime variable with name birthdate.
    • Then creates public properties for the private fields of the class and mark each property with the DataMember attribute so that the property will be serialized when sent to the client.
  2. At this point we have created and configured our data contract and it is ready to be used.

Create & Configure the WCF Service Contract

  1. Open the ICustomer.cs file by double clicking on it in the Solution Explorer.
  2. Add a reference to the following namespaces using the following using statements
using System.Net.Security;
using System.ServiceModel.Web;
  1. The System.Net.Security namespace provides network streams for secure communications between hosts.
  2. The System.ServiceModel.Web Namespace contains classes that make up the Web Http Programming Model.
  3. Replace the code added by default in the ICustomer.cs interface with the following code
[ServiceContract(Namespace = "http://test.example.net", ProtectionLevel = ProtectionLevel.None)]
public interface ICustomer
{
    [OperationContract(ProtectionLevel = ProtectionLevel.None)]
    [WebGet(BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json,
        ResponseFormat = WebMessageFormat.Json, UriTemplate = "GetCustomer/{customer}")]
    CustomerInfo GetCustomer(string customer);
}
  1. In The above code:
    • The above code Marks the ICustomer interface with the ServiceContract attribute and set the name space and Protection level.
    • Adds an operation GetCustomer in the contract that accepts the customer Id and returns the customer information associated with this Id.
    • Sets the Protection level property of the Operation Contract attribute to None.
    • As our service will be RESTful we mark the GetCustomer operation with WebGet attribute. WebGet represents an attribute indicating that a service operation is logically a retrieval operation and that it can be called by the WCF REST programming model.
    • Sets the BodyStyle to Bare, so that the result of the service operations is written directly to the body of the response message.
    • Sets the format of requests made to our service operations to be JSON.
    • Sets the format of responses sent from our service operations to be JSON.
    • Sets the Uniform Resource Identifier (URI) template for our service operation.
  2. At this point we have finished the service contract. Let’s start implementing the service and return data.

Implement the WCF REST Service

  1. Open the Customer.cs file by double clicking on it from the Solution Explorer.
  2. Remove the code added by default by Visual Studio.
  3. Add a reference to the following namespaces using the following using statements
using System.ServiceModel.Web;
using System.ServiceModel.Activation;
using System.Threading;
  1. The System.ServiceModel.Web Namespace contains classes that make up the Web Http Programming Model.
  2. The System.ServiceModel.Activation Namespace provides classes related to service model activation.
  3. The System.Threading namespace provides classes and interfaces that enable multithreaded programming. In addition to classes for synchronizing thread activities and access to data such as the Monitor class that we use.
  4. Replace the code added by default in the Customer.cs interface with the following code
[ServiceBehavior(Namespace = "http://test.example.net", InstanceContextMode = InstanceContextMode.Single,
    ConcurrencyMode = ConcurrencyMode.Multiple, AddressFilterMode = AddressFilterMode.Any)]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class Customer : ICustomer
{
    private List<CustomerInfo> customers;

    public Customer()
    {
        customers = new List<CustomerInfo>();
        customers.Add(new CustomerInfo()
        {
            CustomerId = 3456,
            CustomerName = "Muhammad",
            Address = "any address",
            Birthdate = DateTime.Now.AddYears(-20).Date,
            Email = "Makhaly_cs@msn.com",
            Mobile = "0123467890",
            Phone = "53635363535"
        });

        customers.Add(new CustomerInfo()
        {
            CustomerId = 19008,
            CustomerName = "Jone",
            Address = "any address",
            Birthdate = DateTime.Now.AddYears(-40).Date,
            Email = "Jone@example.com",
            Mobile = "0123467666890",
            Phone = "53635363666535"
        });

        customers.Add(new CustomerInfo()
        {
            CustomerId = 56778,
            CustomerName = "Henry",
            Address = "any address",
            Birthdate = DateTime.Now.AddYears(-34).Date,
            Email = "Henry@example.com",
            Mobile = "0123456785590",
            Phone = "5363536553535"
        }); 

        customers.Add(new CustomerInfo()
        {
            CustomerId = 12233,
            CustomerName = "Anthony",
            Address = "any address",
            Birthdate = DateTime.Now.AddYears(-28).Date,
            Email = "Anthony@example.com",
            Mobile = "012346557890",
            Phone = "5363536553535"
        });

        customers.Add(new CustomerInfo()
        {
            CustomerId = 5677,
            CustomerName = "Scott",
            Address = "any address",
            Birthdate = DateTime.Now.AddYears(-22).Date,
            Email = "Scott@example.com",
            Mobile = "0123469997890",
            Phone = "53635363999535"
        });

        customers.Add(new CustomerInfo()
        {
            CustomerId = 433,
            CustomerName = "Katrien",
            Address = "any address",
            Birthdate = DateTime.Now.AddYears(-30).Date,
            Email = "Katrien@example.com",
            Mobile = "0123469997890",
            Phone = "53635363999535"
        });

        customers.Add(new CustomerInfo()
        {
            CustomerId = 2344,
            CustomerName = "Julie",
            Address = "any address",
            Birthdate = DateTime.Now.AddYears(-35).Date,
            Email = "Julie@example.com",
            Mobile = "01234699887890",
            Phone = "536353688763535"
        });
    }

    [OperationBehavior]
    public CustomerInfo GetCustomer(string customer)
    {
        try
        {
            Monitor.Enter(customers);

            int customerId;
            int.TryParse(customer, out customerId);

            if (customers.Any(customerInfo => customerInfo.CustomerId == customerId))
            {
               CustomerInfo requiredCustomer = customers.Where(customerInfo =>
                    customerInfo.CustomerId == customerId).First();
               return requiredCustomer;
            }
            else
            {
               throw new WebFaultException<string>("There is no customer with this Id.",
                    System.Net.HttpStatusCode.NoContent);
            }
        }
        catch (Exceptionex)
        {
            throw new WebFaultException<string>(ex.Message, System.Net.HttpStatusCode.ServiceUnavailable);
        }
        finally
        {
            Monitor.Exit(customers);
        }
    }
}
  1. In The above code:
    • The above code adds the ServiceBehavior attribute and sets the namespace.
    • We set service behavior InstanceContextMode property to InstanceContextMode.Single so that one object is used for all incoming calls and is not recycled subsequent to the calls.
    • We set service behavior ConcurrencyMode propery to ConcurrencyMode.Multiple so that he service is instance is multi-threaded.
    • We set service behavior AddressFilterMode property to AddressFilterMode.Any which indicates a filter that matches on any address of an incoming message.
    • We create a List CustomerInfo that will be used to hold customers data.
    • In the constructor of the Customer service class we add some dummy data for the purpose of the example. You can get data from database or XML files or any other data source.
    • In the GetCustomer method we first place a try block to catch exceptions.
    • As our service is multi-threaded we allow only one thread to access this method by using Monitor.Enter method and passing to it the list of customers we load in the constructor.
    • As our method uses UriTemplate,we can’t pass any other data types except string data type.
    • We declare an integer variable to hold the customer Id and parse the provided customer into it.
    • We then use the Any method provided by LINQ to objects to check if that the customer list contains a customer with the provided customer Id and return it if exist.
    • If there is no customer with this Id we throw a WebFaultException that takes a string and HTTP Status code. We return HTTP Status Code 204 No Content.
    • In case of any Exceptions we return the exception message and an HTTP Status Code 503 Service Unavailable.
  2. We have created the service contract and implement it. But there is one step left configure the WCF REST Service. Let’s configure it now!

Configure the WCF REST Service

  1. Open the App.config file under the WcfRestService project by double clicking it in the Solution Explorer.
  2. Our work will be in the system.serviceModel configuration element.
  3. Replace the system.serviceModel with following configuration section.
<system.serviceModel>
  <services>
    <service name="WcfRestService.Customer" behaviorConfiguration="CustomerServiceBehavior">
      <endpoint address="" binding="webHttpBinding" bindingConfiguration="webHttpBinding"
                behaviorConfiguration="CustomerEndpointBehavior" contract="WcfRestService.ICustomer">
        <identity>
          <dns value="localhost"/>
        </identity>
      </endpoint>
      <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
      <host>
        <baseAddresses>
          <add baseAddress="http://localhost:8732/Design_Time_Addresses/WcfRestService/Service1/"/>
        </baseAddresses>
      </host>
    </service>
  </services>
  <behaviors>
    <endpointBehaviors>
      <behavior name="CustomerEndpointBehavior">
        <webHttp automaticFormatSelectionEnabled="False" defaultBodyStyle="Bare"
                  defaultOutgoingResponseFormat="Json" faultExceptionEnabled="False" helpEnabled="False"/>
      </behavior>
    </endpointBehaviors>
    <serviceBehaviors>
      <behavior name="CustomerServiceBehavior">
        <serviceMetadata httpGetEnabled="True"/>
        <serviceDebug includeExceptionDetailInFaults="True"/>
      </behavior>
    </serviceBehaviors>
  </behaviors>
  <serviceHostingEnvironment aspNetCompatibilityEnabled="False" multipleSiteBindingsEnabled="True"/>
  <bindings>
    <webHttpBinding>
      <binding name="webHttpBinding" closeTimeout="00:01:00" openTimeout="00:01:00"
       receiveTimeout="00:02:00" sendTimeout="00:02:00" maxBufferSize="524288"
       maxBufferPoolSize="524288" maxReceivedMessageSize="524288" writeEncoding="utf-8"
       transferMode="Buffered">
        <security mode="None">
          <transport clientCredentialType="None" proxyCredentialType="None" />
        </security>
      </binding>
    </webHttpBinding>
  </bindings>
</system.serviceModel>
  1. In The above code:
    • The above configuration element configures our service endpoint to use the webHttpBinding. webHttpBinding is a binding used to configure endpoints for Windows Communication Foundation (WCF) Web services that are exposed through HTTP requests instead of SOAP messages.
    • We configure the webHttpBinding and set its close timeout to 1 minute, its open timeout to 1 minute, its receive timeout to 2 minutes, send timeout to 2 minutes, and write encoding to UTF-8 encoding.
    • We add a service behavior named CustomerServiceBehavior. In this service behavior we enable getting service metadata using HTTP protocol. Also we enable the return of any unhandled exception in the response body message.
    • We add an endpoint named CustomerEndpointBehavior. We add a webHttp element. This element specifies the WebHttpBehavior on an endpoint through configuration. This behavior, when used in conjunction with the webHttpBinding standard binding, enables the Web programming model for a Windows Communication Foundation (WCF) service.
    • At the endpoint element we set bindingConfiguration to webHttpBinding and behaviorConfiguration to CustomerEndpointBehavior that we create earlier.
    • At the service element we set behaviorConfiguration to CustomerServiceBehavior we have created earlier.
  2. After configuring the service we need to host it on IIS and test its operations. Let’s test it now.

Publish the WCF REST Service

  1. Build your WCF REST Service by write Clicking on the project in Solution Explorer and select Build.
  2. Right click the WcfRestService in Solution Explorer and select Publish. The Publish WCF Service Dialog appears.
  3. Type the path you want to publish to and the copy options.
  4. Click Publish to publish the service to the selected path.

WcfRestService

Host the WCF REST Service in IIS 7.5

  1. Open Internet Information Services (IIS)
  2. In the left pane expand the Current Server name.
  3. Expand Sites and then Default Web Site.
  4. Right Click on Default Web Site and select Add Application. The Add Application Dialog appears.
  5. Type the alias name of the application.
  6. Select the path that we have published the service to earlier.
  7. Click OK to Add the Application.

WcfRestService

  1. After you add the application click on it and switch to content view.

WcfRestService

  1. Right click on the WcfRestService.Customer.svc and select Browse. It will display a page like the following image in your default browser.

WcfRestService

Test the WCF REST Service

  1. After you browse the service we need to make sure it is running.
  2. Append the following string to the service Uri “/GetCustomer/3456”, so we get information for customer number 3456. And the result of the call is something similar to the following image

WcfRestService

  1. If you type a customer Id the does not exist in the list of customers it will respond with something similar to the following image.

WcfRestService


Now you have a WCF REST Service that returns specific HTTP Status Codes for specific situations such as where there is no data to return in a search query he want to return HTTP 204 No Content and HTTP 503 Service Unavailable when there is an unhandled exceptions.

Similar Posts