Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Generic WCF RestFul Service for an iPad Application

27 Aug 2012CPOL1 min read 13.3K  
WCF Restful Service which accept data from iPad in any form. e.g JSON, XML, Plain text

Introduction

Nowadays WCF Restful services are in news because they can be connected over "Web" with HTTP request/response messages. But the Request and Response format could be either JSON or XML. There are many articles available on web which can pass data in JSON or XML format to the WCF Restful service and receive data in JSON or XML format. Here i am going to show you how to pass data to WCF Restful service in any form e.g JSON, XML, Plain text, Nested JSON etc.

Background 

This service will accept Log Content which is in JSON format, XML Format or any other format generated by an iPad application and store it in the sql server database.

 Image 1

The service has been made generic so that it can accept data in any form.

Using the code 

The method signature is provided below

Interface: ILoggingService

C#
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "/PostGenericLogData", 
   BodyStyle = WebMessageBodyStyle.Wrapped, ResponseFormat = WebMessageFormat.Json)]
MessageDetails AddLogDetails(Stream genericData);

Service Interface contains a method called AddLogDetails which accept data of type Stream.

C#
public MessageDetails AddLogDetails(Stream genericData)
{
    string input = new StreamReader(genericData).ReadToEnd();

    MessageDetails messageDetails = new MessageDetails();

    try
    {
        string serverName = "", databaseName = "", integratedSecurity = "";

        //path where the config file resides on server
        XmlTextReader textReader = new XmlTextReader("C:\\Config.xml");

        //Get the required connection string details from the config.xml file

        while (textReader.Read())
        {
            XmlNodeType ntype = textReader.NodeType;
            if (ntype == XmlNodeType.Element)
            {
                switch (textReader.Name)
                {
                    case "DataBaseServerName":
                        textReader.Read();
                        serverName = textReader.Value;
                        break;
                    case "DatabaseName":
                        textReader.Read();
                        databaseName = textReader.Value;
                        break;
                    case "IntegratedSecurity":
                        textReader.Read();
                        integratedSecurity = textReader.Value;
                        break;
                }
            }
        }

        int index = input.IndexOf('|');

        int len = input.Length - index;

        if (index == 0 || index == -1)
        {
            messageDetails.Status = "Fail";
            messageDetails.Error = "Source Type is missing";
        }
        else if (len == 1)
        {
            messageDetails.Status = "Fail";
            messageDetails.Error = "Log Content is missing";
        }
        else
        {
            string logType = input.Substring(0, index);
            string logContent = input.Substring(index + 1, len - 1);

            using (SqlConnection cn = new SqlConnection())
            {
                // prepare connection and command
                cn.ConnectionString =
                  string.Format(
                  "data source={0};initial catalog={1};integrated security={2};",
                    serverName,
                    databaseName,
                    integratedSecurity
                );
                cn.Open();
                SqlCommand cmd = new SqlCommand();
                cmd.Connection = cn;
                cmd.CommandText = "dbo.Log_UserDetails";

                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Parameters.AddWithValue("@SourceType", logType);
                cmd.Parameters.AddWithValue("@LogContents", logContent);
                // execute stored procedure

                int result = cmd.ExecuteNonQuery();

                cn.Close();

                if (result == 1)
                    messageDetails.Status = "Success";
                else
                {
                    messageDetails.Status = "Fail";
                    messageDetails.Error = "ExecuteNonQuery returns " + 
                      result.ToString() + 
                      " as result, which is nothing but number of rows affected";
                }
            }
        }
    }
    catch (Exception ex)
    {
        messageDetails.Status = "Fail";
        messageDetails.Error = ex.Message;
    }
    return messageDetails;
}

A class called MessageDetails is created which contains following DataMember:

C#
public class MessageDetails
{
    string status;
    string error;

    [DataMember]
    public string Status
    {
        get { return status; }
        set { status = value; }
    }

    [DataMember]
    public string Error
    {
        get { return error; }
        set { error = value; }
    }

}

Limitations: WCF REST service accepts only one parameter 

Method: POST

Response Type: JSON

How to call service from REST Client 

Go to https://addons.mozilla.org/en-US/firefox/addon/restclient/ and download REST Client

Image 2

Following steps needs to be followed to call WCF REST service from client app.

Method: POST

URL: WCF Service URL

Headers: Content-Type: application/x-www-form-urlencoded

Post Data \ Body: Source Type | Log Content

Points of Interest

Even though this service accepts only one parameter we can append various parameters using the separator and pass it to the service. In this service I have used a | separator and appended the source type and log content.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)