Click here to Skip to main content
Click here to Skip to main content

How to access SQL database from an iPhone app Via RESTful WCF service hosted on IIS 7.5

By , 19 Jun 2012
 

Introduction 

If you are looking for a way to access a Microsoft SQL database from mobile phones like Android or iPhone, and would like an example on how to do it and test it, then may be this will help you. 

Background        

One way to get at SQL data from a mobile app is via a RESTful WCF service. The WCF service will expose the database and return JSON data which can get consumed by an iPhone app using http requests.

This article assumes that you have a basic understanding of WCF, SQL database, and iPhone programming. In this tutorial, I will build a WCF service that exposes a simple SQL database "EmpDB", host the service on IIS 7.5, and return the Employee info in JSON format, which will get consumed in an iPhone Application. This example is built with the following tools: VS2010, SQLServer 2008, .Net Framework 4.0, and iOS 5.   

Why JSON not XML?    

  1. Better representation of language-independent Data Structures
  2. Simple, well defined, easy to parse, and easy to read.  
  3. lightweight payload = reduced bandwidth = faster transfers 
  4. iOS has nice native JSON SDKS, which makes it easy to parse and super fast.  

Using the code      

If you already have a SQL database on your machine that you would like to expose, then skip to step #1. Otherwise, create a simple SQL database, and for consistency purposes, you can use a SQL database like mine. Call it "EmpDB", create one table "EmpInfo" with three fields:     

  • firstname (nchar(10) type)       
  • lastname  (nchar(10)  type)    
  • salary  (decimal type)          

As you can see, I have 5 records in my database that I would like to get into my iPhone app. 

Here are five simple steps required to accomplish the goal: 

  1. Create a new WCF service  
  2. Add Interface Code 
  3. Implement Service    
  4. TEST the service remotely  
  5. Consume JSON from mobile apps like iOS?   

1.Create a new WCF service 

File>New project>C#>WCF Service>"JsonWcfService" 

Delete the automatically generated IService1.cs and Service1.svc files. We will create our own. 

Add WCF service: FILE>new item>C#>WCF service>"GetEmployees.svc".  

This will create two files, the interface "IGetEmployee.svc" and the service implementation file "GetEmployee.svc". 

2. Add Interface Code    

Add the following code to the interface "IGetEmployee file"

using System.ServiceModel.Web;
 
namespace JsonWcfService
{
    [ServiceContract]
    public interface IGetEmployees
    {
        [OperationContract]
        //attribute for returning JSON format
        [WebInvoke(Method = "GET",
            ResponseFormat = WebMessageFormat.Json,
            BodyStyle = WebMessageBodyStyle.Wrapped,
            UriTemplate = "json/employees")]
        //method
        List<Employee> GetAllEmployeesMethod();
    }
} 

Add a reference to System.ServiceModel.Web. If this framework wasn't available, right click on project > properties > Application Tab> Target> and make sure .Net Framework 4.0 is selected.   

The WebInvoke attribute before the method ensures that data is returned in JSON fornmat. This could have been WebMessageFormat.Xml, if you are interested in returning XML instead.   

The interface has one method "GetAllEmployeesMethod", which returns a list of employees from the database. This method will need to be implemented in our service code in the next step.  

  

3. Implement Service 
Add the following code to Implementation file "GetEmployees.svc". This service file implements the interface method "GetAllEmployeesMethod". In this method, I simply open a basic connection to a local SQL database "EmpDB" with all defaults to keep it simple. I query the "EmpInfo" table by asking to get a list of all the employees with their firstname, lastname and salary. Make sure to add a reference to System.Data.SqlClient fto expose SQL operations, and System.Runtime.Serialization to expose [DataContract]  attribute like shown in the images below.  

using System.Data.SqlClient;
using System.Runtime.Serialization;
namespace JsonWcfService
{
    public class GetEmployees : IGetEmployees
    {
       public List<Employee> GetAllEmployeesMethod()
        {
             List<Employee> mylist = new List<Employee>();
 
            using (SqlConnection conn = new SqlConnection("server=(local);database=EmpDB;Integrated Security=SSPI;"))
            {
                conn.Open();
 
                string cmdStr = String.Format("Select firstname,lastname,salary from EmpInfo");
                SqlCommand cmd = new SqlCommand(cmdStr, conn);
                SqlDataReader rd = cmd.ExecuteReader();
               
                if (rd.HasRows)
                {
                    while (rd.Read())
                        mylist.Add(new Employee(rd.GetString(0), rd.GetString(1), rd.GetDecimal(2)));
                }
                conn.Close();
            }
 
            return mylist;
        }
    }
 
    [DataContract]
    public class Employee
    {
        [DataMember]
        public string firstname { get; set; }
        [DataMember]
        public string lastname { get; set; }
        [DataMember]
        public decimal salary { get; set; }
        public Employee(string first, string last, decimal sal)
        {
            firstname=first;
            lastname=last;
            salary=sal;
        }
    }
}   

Now, tweak the web.config file within the project's solution explorer like this. Note I used binding="webHttpBinding" and <webHttp/>. Project won't work correctly without these tweaks!     

<services>
      <service name="JsonWcfService.GetEmployees" behaviorConfiguration="EmpServiceBehaviour">
        <endpoint address ="" binding="webHttpBinding" contract="JsonWcfService.IGetEmployees" behaviorConfiguration="web">
        </endpoint>
      </service>
    </services>
 
    <behaviors>
      <serviceBehaviors>
        <behavior name="EmpServiceBehaviour">
          <serviceMetadata httpGetEnabled="true"/>
         <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
      <endpointBehaviors>
        <behavior name="web">
          <webHttp/>
        </behavior>
      </endpointBehaviors>
    </behaviors>

This is it for WCF service. Compile in Release and Debug modes. Run by ctrl+F5, this will open a browser that displays GetEmployeeService, like http://localhost:7794/GetEmployees.svc. Well if you want to see the Employees list, you can type this into the browser: http://localhost:7794/GetEmployees.svc/json/employees 

The WCF service returns our employees list from the database in JSON format and is hosted in IIS. But, how can I get the employees list into my iPhone or Android Application and be able to test it? 

What we did so far can only be tested on the same development machine, but can't get to it from a different machine or from an iphone app which is our goal. To do that, we need to host the service using some website. To do this, you need to pick a folder somewhere that will contain the necessary files to run the website.

4. TEST the service remotely  

To create and run the website: 

- Make a new folder C:/JsonWcfService. Two files will go here: a .svc file and web.config file.   

- Under C:/JsonWcfService, open new notepad file, name it "GetEmployees.svc", and place the following line in it:  

<% @ServiceHost Service="JsonWcfService.GetEmployees" %>  

- Open new notepad file, place the following code in it, and name it "web.config". Basically, the endpoints and service behaviors here have to match the web.config from your service in Visual Studio 

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <services>
      <service name="JsonWcfService.GetEmployees" behaviorConfiguration="EmpServiceBehaviour">
        <endpoint address ="" binding="webHttpBinding" contract="JsonWcfService.IGetEmployees" behaviorConfiguration="web">
        </endpoint>
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8000/" />
          </baseAddresses>
        </host>
      </service>
    </services>
    
    <behaviors>
      <serviceBehaviors>
        <behavior name="EmpServiceBehaviour">
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
      <endpointBehaviors>
        <behavior name="web">
          <webHttp/>
        </behavior>
      </endpointBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>   

- Make a new subfolder C:/JsonWcfService/bin, and copy "JsonWcfService.dll" from your ~project/bin directory to C:/JsonWcfService/bin.   

- Now, we just need to add the website in IIS7.5 and point to the folder we just created:    

  • Open IIS(Internet Innformation Services) manager from cmd prompt or from windows search box  
  • Under Connections tree, expand "sites" > Right Click on Default Web Site > Add Application
  • use "JsonWcfService" for alias and Browse to folder "C:\JsonWcfService" for physical path
  • press ok   

 

This is it. To get the employees list from same machine, type the following link in your browser: http://localhost/JsonWcfService/GetEmployees.svc/json/employees 

To get the employees list from a remote machine on your intranet: http://"yourIPAddress"/JsonWcfService/GetEmployees.svc/json/employees      

Replace "yourIPAddress" by the IP address of the machine that hosts your service. Get your IP address: cmd prompt>ipConfig.    

e.g: http://192.168.1.104/JsonWcfService/GetEmployees.svc/json/employees       

5.Consume JSON in an iPhone application 

Luckily, iOS5 has native JSON SDKs that will make this task very straight forward.   

In iOS, add a basic simple View app with 2 UIlabels to display the JSON text, and a more human readable format. Wire them up.

@property (weak, nonatomic) IBOutlet UILabel *jsonText;
@property (weak, nonatomic) IBOutlet UILabel *humanText;  

Add the following code to your viewDidLoad method:   

//wcf service
#define WcfSeviceURL [NSURL URLWithString: @"http://192.168.1.102/JsonWcfService/GetEmployees.svc/json/employees"]
 
- (void)viewDidLoad
{
    [super viewDidLoad];
    NSError *error = nil;
    NSData *data = [NSData dataWithContentsOfURL:WcfSeviceURL options:NSDataReadingUncached error:&error];
    jsonText.text = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
 
    if(!error)
    {
        NSDictionary* json = [NSJSONSerialization 
                              JSONObjectWithData:data 
                              options:NSJSONReadingMutableContainers 
                              error:&error];  
        
        NSMutableArray *array= [json objectForKey:@"GetAllEmployeesMethodResult"];
        
        for(int i=0; i< array.count; i++)
        {
            NSDictionary *empInfo= [array objectAtIndex:i];
            
            NSString *first = [empInfo objectForKey:@"firstname"];
            NSString *last = [empInfo objectForKey:@"lastname"];
            NSString *salary  = [empInfo objectForKey:@"salary"];
            
            //Take out whitespaces from String
            NSString *firstname = [first
                                   stringByReplacingOccurrencesOfString:@" " withString:@""];
            NSString *lastname = [last
                                   stringByReplacingOccurrencesOfString:@" " withString:@""];
            
            humanText.text= [humanText.text stringByAppendingString:[NSString stringWithFormat:@"%@ %@ makes $%@.00 per year.\n",firstname,lastname,salary]];
        }
        
    }
}

Notice the use of NSJSONSerialization class, which turns JSON objects to NSFoundation objects, like NSDictionary, NSArray, NSString. So, NSDictionary* json contains the list of employees. 

So, here is the employees list output displayed in your iPhone app in JSON and human human formats 

r    

Points of Interest  

The article provides you with a taste of how to access data across platforms. With the growing demand in the mobile industry, going across the boundaries becomes a must. It is often the case that mobile apps would like to communicate with other servers and databases. Restful WCF is a nice lightweight solution which can return JSON or xml and allows to be consumed by different technologies, which makes it very flexible for the future. WCF services provide a great alternative for traditional web services.

History  

V1.0 June 18, 2012

License

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

About the Author

Samer M. Abdallah
Technical Lead
United States United States
Member
I am a Lead Software Developer and application analyst. I have over 10 years of experience in Embedded real-time systems development, GUI, databases, mobile development, and back-end web development.

My skill Set: OOD, C/C++, C#, ASP.NET, ADO.NET, JavaScript, WCF, iPhone, SQL Server,Oracle 10g, Apache Solaris, Unix, Linux.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
Questionhow to setting IISmembermvtt.uit9120 Mar '13 - 23:52 
Hi Samer M. Abdallah,
Thanks you verry much.
but, when 4. TEST the service remotely i do same you but it not work.
i don't know setting IIS to run it.
can't you suport me step by step.
thanks( my english not good Smile | :) )
QuestionA best way to success this Articlemembernickykiet8331 Dec '12 - 21:04 
My advice is change connectionstring in this article to:
"Data Source=(local);Initial Catalog=EmpDB;user=sa;pwd=yourpass"
instead of:
"server=(local);database=EmpDB;Integrated Security=SSPI;"
 

If you want to use Integrated Security=SSPI, you must be master of IIS Management to config.
Questionupdate or insert data from iPhonemembermilon_bd27 Dec '12 - 19:47 
How to get data passed from client to server side?can you explain plz.....??
SuggestionA lot of setting needs to be done [modified]memberdongsuyangflkl4 Oct '12 - 10:52 
It is a very helpful article for a newbie, like me.
However I tried this for two days, and found out there were several settings that haven't been mentioned in the article before the server functions.
 
0. Same suggestion as the following post "
Quote:
HTTP Error 404.0 - Not Found - works now !
"
1. database name
Dont't forget to set the server's name correctly. This is what I do in my case
new SqlConnection("server=your_computer_name\\SQLEXPRESS;
your_computer_name is the computer's name. You can actually find out the server's name from SQL server management studio.
 
2. parameter
In case you don't just want a static sql statement
WHERE Comment.BusinessId = @id
cmd.Parameters.Add(new SqlParameter("id", Convert.ToInt32(businessId)));
 
same thing for uritemplate
UriTemplate = "json/usercomments/businessId={businessId}")]
// method
List<UserComment> GetUserCommentsMethod(string businessId);
 
3. publish
the publish method doesn't work for me no matter how hard I tried. Instead I right click on the project name and select publish. This solves every problem.
http://msdn.microsoft.com/en-us/library/dd465337.aspx[^]
 
4. access the database from a remote computer
I need to change the identity of 'Application Pools' to the administrator account in the IIS Manager to get it enough priority.
 
5. firewall
Make an exception on the port number. Follow the instruction below:
http://blog.aquabirdconsulting.com/2010/01/19/windows-7-open-firewall-ports-to-iis7/[^]
 
6. web.config access
In some occasion, this link might be helpful to solve web.config access issue:
http://stackoverflow.com/questions/8939342/cannot-read-configuration-file-due-to-insufficient-permissions[^]

modified 15 Oct '12 - 17:35.

QuestionHTTP Error 404.0 - Not Found - works now !memberMember 775694126 Sep '12 - 12:45 
had to do the following for the "HTTP Error 404.0 - Not Found" error
 
Step 1. the options under Programs->Turn Windows features on or off- > Micorsoft .net framework 3.5.1, on my Windows 7 were unchecked. I enabled these; Windows Communication Foundation HTTP ACtivation and Windows Communication Foundation non-http Activation
 
After the above was set, gave a different error while invoking the site from Browser
 
Step 2: aspnet_regiis.exe -i ( this is under microsoft.net\framework\v4...\)
 
Step 3: While setting up site under "Default Web Site" under IIS, has to use "Connect as" instead of Pass-through auth. The "Test Setting" option failed in Pass-through mode.
QuestionAdding ParametersmemberMember 939115829 Aug '12 - 2:40 
I got the IIS service to work, now working on the Objective-C Code. How can I pass parameters to this service to query another table/view? (i.e. send param "items" for the items table, send param "salesman" for a query of the salesman table)
AnswerRe: Adding ParametersmemberH49213 Nov '12 - 3:56 
Have you discovered a solution you might share?
QuestionIIS set upmemberSuperspec21 Aug '12 - 23:04 
Having many years experience of such things, to get these examples to work you need to have IIS set up correctly for ASP.net etc.
 
It would be helpful if you briefly described the IIS set up you are using since my set up is bringing up 404 errors ??
 
I don;t currently have time to play what ACL's do you have are you running the latest .NET build ?
 
Mad | :mad: Mad | :mad:
Questionit works...but how to send json back from iphone to wcf?membersscorpio4 Aug '12 - 3:01 
What schould i write on wcf side to send json back from iphone to database?
AnswerRe: it works...but how to send json back from iphone to wcf?memberSamer M. Abdallah10 Aug '12 - 5:54 
You create a URLRequest with JSON data from iphone. Here is an example of how to insert Employee record into database.
 
From iPhone:
-(void) insertEmployeeMethod
 
{
 
    if(firstname.text.length && lastname.text.length && salary.text.length)
 
    {
 
        NSString *str = [BaseWcfUrl stringByAppendingFormat:@"InsertEmployee/%@/%@/%@",firstname.text,lastname.text,salary.text];
 
        NSURL *WcfSeviceURL = [NSURL URLWithString:str];
        NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
 
        [request setURL:WcfSeviceURL];
 
        [request setHTTPMethod:@"POST"];
 
        // connect to the web
 
        NSData *respData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
 
        // NSString *respStr = [[NSString alloc] initWithData:respData encoding:NSUTF8StringEncoding];
 

        NSError *error;
 
        NSDictionary* json = [NSJSONSerialization 
 
                              JSONObjectWithData:respData 
 
                              options:NSJSONReadingMutableContainers 
 
                              error:&error];  
 
        
 
        NSNumber *isSuccessNumber = (NSNumber*)[json objectForKey:@"InsertEmployeeMethodResult"];
 
        
  //create some label field to display status
        status.text = (isSuccessNumber && [isSuccessNumber boolValue] == YES) ? [NSString stringWithFormat:@"Inserted %@, %@",firstname.text,lastname.text]:[NSString stringWithFormat:@"Failed to insert %@, %@",firstname.text,lastname.text];
    }
 
}
 
in WCF interface:
 //Insert
        [OperationContract]
        [WebInvoke(Method = "POST",
            ResponseFormat = WebMessageFormat.Json,
            RequestFormat = WebMessageFormat.Json,
            BodyStyle = WebMessageBodyStyle.Wrapped,
            UriTemplate = "json/InsertEmployee/{id1}/{id2}/{id3}")]
        bool InsertEmployeeMethod(string id1,string id2, string id3);
 
In Implementation:
//insert to DataBase
       public bool InsertEmployeeMethod(string id1,string id2, string id3)
       {
 
           int success = 0;
 
           using (SqlConnection conn = new SqlConnection("server=(local);database=EmpDB;Integrated Security=SSPI;"))
           {
               conn.Open();
 
               decimal value= Decimal.Parse(id3);
               string cmdStr = string.Format("INSERT INTO EmpInfo VALUES('{0}','{1}',{2})",id1,id2,value);
               SqlCommand cmd = new SqlCommand(cmdStr, conn);
               success = cmd.ExecuteNonQuery();
    
               conn.Close();
           }
 
           return (success != 0 ? true : false);
       }

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130523.1 | Last Updated 19 Jun 2012
Article Copyright 2012 by Samer M. Abdallah
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid