Archive

Archive for the ‘WCF’ Category

Android with WCF Services

March 1, 2012 24 comments

These days, android-based phones are gaining popularity and great apps are available and built every day to enhance its popularity. At this time, I want to work on android development and trying to find out how to communicate android with my existing application. The simplest way to do this is to expose the services to enable communication between android and my existing applications. In this blog post, I am going to look at how android can make use of WCF Services. But before moving forward, I would emphasize that since Android does not provide great support of XML or SOAP-based services, we are going to build WCF Restful Services responsible for providing response in JSON format. So, let’s start by looking first at how we can create WCF services.

I will begin by creating a WCF application named “EmployeeServices “with VS 2010 and deploy it on IIS Server. Although VS2010 provides us with a development server where we can test our services, Android will not be able to communicate withVS2010 Development Server, hence you would be required to deploy your services at IIS and with help from your local system IP address, provide DNS to Android.

Settings -> Wireless Control -> Mobile Networks -> Access Point Names, Select the active and replaced the proxy and port of your DNS

The Employee Entity is mention below

[DataContract]
public class Employee
{
[DataMember]
public int EmployeeId { get; set; }
[DataMember]
public string FirstName { get; set; }
[DataMember]
public string LastName { get; set; }
[DataMember]
public string Address { get; set; }
[DataMember]
public string BloodGroup { get; set; }
}

Here is the code of Contract and Services

[ServiceContract(Namespace = "http://services.example.com")]
public interface IEmployeeInfo
{
[OperationContract]
[WebGet(UriTemplate = "GetEmployee/?key={employeeId}" )]
Employee GetEmployee(int employeeId);
}

public class EmployeeInfo : IEmployeeInfo
{
public Employee GetEmployee(int employeeId)
{
Employee employeeInfo = GetEmployees().Where(employee => employee.EmployeeId == employeeId).FirstOrDefault();

return employeeInfo;
}

private List<Employee> GetEmployees()
{
return new List<Employee> {
new Employee { EmployeeId = 11, FirstName = "Waqas", LastName = "Yousuf", Address="A-175 Block 1" , BloodGroup = "B+" },
new Employee { EmployeeId = 22, FirstName = "Moiz", LastName = "Ahmed", Address="B-176 Block 2" , BloodGroup = "O-" },
new Employee { EmployeeId = 33, FirstName = "Waqas", LastName = "Raza", Address="C-177 Block 3" , BloodGroup = "A+" },
new Employee { EmployeeId = 44, FirstName = "Yasir", LastName = "Amin", Address="D-178 Block 4" , BloodGroup = "AB+" },
new Employee { EmployeeId = 55, FirstName = "Adeel", LastName = "Ali", Address="E-179 Block 5" , BloodGroup = "B+" },
new Employee { EmployeeId = 66, FirstName = "Fahad", LastName = "Ahmed", Address="F-180 Block 6" , BloodGroup = "B+" },
new Employee { EmployeeId = 77, FirstName = "Mahboob", LastName = "Ikram", Address="G-181 Block 7" , BloodGroup = "B+" },
new Employee { EmployeeId = 88, FirstName = "Saif", LastName = "Ali", Address="H-182 Block 8" , BloodGroup = "O+" },
new Employee { EmployeeId = 99, FirstName = "Nasir", LastName = "Saleem", Address="J-183 Block 9" , BloodGroup = "B+" },
new Employee { EmployeeId = 111, FirstName = "Yasir", LastName = "Shah", Address="I-184 Block 10" , BloodGroup = "O+" },
new Employee { EmployeeId = 222, FirstName = "Saad", LastName = "Usman", Address="J-185 Block 11" , BloodGroup = "B+" },
new Employee { EmployeeId = 333, FirstName = "Yaseen", LastName = "Wahid", Address="K-186 Block 12" , BloodGroup = "B+" },
new Employee { EmployeeId = 444, FirstName = "Qasim", LastName = "Wasi", Address="L-187 Block 13" , BloodGroup = "B+" },
new Employee { EmployeeId = 555, FirstName = "Asad", LastName = "Tamoor", Address="M-188 Block 14" , BloodGroup = "A+" },
new Employee { EmployeeId = 666, FirstName = "Idress", LastName = "Khan", Address="N-189 Block 15" , BloodGroup = "B+" },
new Employee { EmployeeId = 777, FirstName = "Rafa", LastName = "Rauf", Address="O-190 Block 16" , BloodGroup = "B+" },
new Employee { EmployeeId = 888, FirstName = "Fazain", LastName = "Farooq", Address="P-191 Block 17" , BloodGroup = "B+" },
new Employee { EmployeeId = 999, FirstName = "Ali", LastName = "Akber", Address="Q-192 Block 18" , BloodGroup = "B+" },
new Employee { EmployeeId = 1111, FirstName = "Irfan", LastName = "Khan", Address="R-193 Block 19" , BloodGroup = "B+" },
new Employee { EmployeeId = 2222, FirstName = "Omair", LastName = "Ali", Address="S-194 Block 20" , BloodGroup = "B+" },
new Employee { EmployeeId = 3333, FirstName = "Wasi", LastName = "Ahmed", Address="T-195 Block 21" , BloodGroup = "B+" },

};
}
}

Now here is the Code for Web.Config File.

<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<standardEndpoints>
<webHttpEndpoint>
<standardEndpoint helpEnabled="true"
automaticFormatSelectionEnabled="true"/>
</webHttpEndpoint>
</standardEndpoints>
<services>
<service name="EmployeeService.EmployeeInfo">
<endpoint kind="webHttpEndpoint"
contract="EmployeeService.IEmployeeInfo" />
</service>
</services>
</system.serviceModel>
</configuration>

In the WCF services I created an Employee Entity which has some employee information properties, and wrote a method which provides the collection of dummy data. You can replace it with your desired repository. To keep things simple, I am going to with simple approach. Next I created a contract in services named “GetEmployee” which is responsible to take the EmployeeID (at some places I refer to it as employee code) and if the matching employee exists the system will provide the complete entity of employee otherwise send it to blank. At the contract, annotate the URI Template,and I am creating an automated formatted service, which means that the same services will provide the data in form of XML or JSON based on the header information of the request. For further clarification, you may refer to one of my previous blog post. WCF 4.0 Automatic Formatting with Jquery Ajax.

Now the services are finalized and it’s time to move towards the Android side. For Android development, I have configured the required ADT plug-in, AVDand Android SDK in Eclipse IDE. Now, I am going to create Android Project named “EmployeeInfo” and click on Next button.

At this stage, I will select ‘Android 2.2’(Froyo)because as AVD I have configured Android 2.2

In the image below, you can find other information where Create Activity name is EmployeeInfoActivity.

Here is the code for EmployeeInfoActivity, in which I am using JSON Object to parse the JSON string I received from services. HttpGet has setter method of header, using which we can request the server for JSON data. Retrieve the data from the server and set them with TextView which are already placed at Android UI.

public class EmploeeInfoActivity extends Activity {

	private final static String EMPLOYEE_SERVICE_URI = "http://192.168.1.3/EmployeeService/EmployeeInfo.svc/GetEmployee/?key=";

	private EditText evEmployeeId;
private TextView tvEmployeeCode;
private TextView tvName;
private TextView tvAddress;
private TextView tvBloodGroup;
	private Button bSearchEmployee;
	private LinearLayout linearLayoutEmp;
	private LinearLayout linearLayoutError;

	/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

evEmployeeId = (EditText)findViewById(R.id.evEmployeeCode);

tvEmployeeCode = (TextView)findViewById(R.id.tvEmployeeCode);
tvName = (TextView)findViewById(R.id.tvEmployeeName);
tvAddress = (TextView)findViewById(R.id.tvAddress);
tvBloodGroup = (TextView)findViewById(R.id.tvBloodGroup);

linearLayoutEmp = (LinearLayout)findViewById(R.id.lLayoutEmployeeInfo);
linearLayoutError = (LinearLayout)findViewById(R.id.lLayoutError);

linearLayoutEmp.setVisibility(View.GONE);
linearLayoutError.setVisibility(View.GONE);
}

public void onSearchClick(View view)
{
try	{

	    	DefaultHttpClient client = new DefaultHttpClient();
	    	// http get request
	    	HttpGet request = new HttpGet(EMPLOYEE_SERVICE_URI + evEmployeeId.getText());

	    	// set the hedear to get the data in JSON formate
	    	request.setHeader("Accept", "application/json");
	        request.setHeader("Content-type", "application/json");

	        //get the response
	        HttpResponse response = client.execute(request);

	        HttpEntity entity = response.getEntity();

	        //if entity contect lenght 0, means no employee exist in the system with these code
	        if(entity.getContentLength() != 0) {
	        	// stream reader object
	        	Reader employeeReader = new InputStreamReader(response.getEntity().getContent());
		        //create a buffer to fill if from reader
	        	char[] buffer = new char[(int) response.getEntity().getContentLength()];
		        //fill the buffer by the help of reader
	        	employeeReader.read(buffer);
		        //close the reader streams
	        	employeeReader.close();

	        	//for the employee json object
		        JSONObject employee =  new JSONObject(new String(buffer));

		        //set the text of text view
		        tvEmployeeCode.setText("Code: " + employee.getString("EmployeeId"));
		        tvName.setText("Name: " + employee.getString("FirstName") + " " + employee.getString("LastName"));
		        tvAddress.setText("Address: " + employee.getString("Address"));
		        tvBloodGroup.setText("Blood Group: " + employee.getString("BloodGroup"));

		        //show hide layout
		        linearLayoutError.setVisibility(View.GONE);
		        linearLayoutEmp.setVisibility(View.VISIBLE);
	        }
	        else {
	        	 linearLayoutEmp.setVisibility(View.GONE);
	        	 linearLayoutError.setVisibility(View.VISIBLE);
	        }

}
catch (Exception e) {
//any exception show the error layout
linearLayoutEmp.setVisibility(View.GONE);
linearLayoutError.setVisibility(View.VISIBLE);
e.printStackTrace();
}

}
}

Now I am going to place control at layout.xml file for UI of the android, Search button is bound with onSearchClick event in EmployeeInfoActivity. One EditText, four TextView objects to display the employee information and if the employee information does not exist or garbage input, then it will display an error message.

After that, we have to put the internet permission in AndroidManifest.xml


<uses-permission android:name="android.permission.INTERNET" />

Now here are the final results:

Now if there is an error, error message(s) will  be displayed:

In this post, I just demonstrated how we can facilitate communication between Android and WCF services, using which we can easily perform all the CURD Operations. I hope you will enjoy the post and give your valuable feedback on it

Happy Coding 🙂

Advertisements
Categories: Android, WCF

WCF 4.0 Automatic Formatting with Jquery Ajax

June 23, 2011 3 comments

As I discussed in my last post about standard endpoints, at this time I am going to look at Automatic Formatting in WCF 4.0.That is one of the great addition in WCF Web HTTP programming model(WCF RESTful). By using this feature it’s dynamically determine the format for the service operation. Previously, if consumed JSON and XML format for the same operation of the service then must have defined two different operations with explicitly annotated RequestFormat parameter of the WebGetAttribute and WebInvokeAttribute attributes.

For getting json format in WCF 3.5

[OperationContract]

[WebGet(RequestFormat = WebMessageFormat.Json)]

string GetJsonData();

For getting Xml format in WCF 3.5

[OperationContract]

[WebGet(RequestFormat = WebMessageFormat.Xml)]

string GetXmlData();

Now we have option either go with explicit as above or go with new automatic way .By default Automatic format selection is disable due to backwards compatibility and when it’s enabled, it would automatically get the best format in which to return the response. WCF infrastructure actually checks the type which is contained the request messages of Accept Header. The first priorities for media types, if it’s not found in Accept Header than its checks the content-type of the request message and if content-type would not give the suitable response than it would be used default format setting which is defined by RequestFormat parameter of the WebGetAttribute and WebInvokeAttribute attributes and at the last if there is no any default format setting than it would be used value of the DefaultOutgoingResponseFormat property.

  1. Priorities of media types in request message’s Accept Header.
  2. The content-type of the request message.
  3. The default format setting in the operation.
  4. The default format setting in the WebHttpBehavior.

Automatic format selection depends on AutomaticFormatSelectionEnabled property. It can be enabled programmatically or using configuration, for getting the clarification I would like to show example of it with Jquery, using  jquery I will be getting the different  format by calling the same operation of the service, for keeping it simple I am enabling the AutomaticFormatSelectionEnabled through standard endpoints, so let’s start it.

First I am going to create an empty web application JqueryWithWCF and hosting it at IIS.

I am going to add following items in the solution.

  • WCFService item named RestfulService.svc , 
  • html page named jqueryPage.htm
  • jquery scripts file.

We have to add System.ServiceModel.Web reference for working with WCF RESTful services.

Now let’s look at the IRestfulService.cs code

namespace WCFRestfulService
{
    [ServiceContract]
    public interface IRestfulService
    {
        [OperationContract]
        [WebGet(UriTemplate = "/data")]
        string GetData();
    }
}

I added ServiceContract attribute at intrface to expose the service and OperationContract attribute for expose the operation out of the world ,now we have to add WebGet attribute with property name UriTemplate=”/data”, it means, it can be called using UriTemplate property name.

Look at the RestfulService.cs code

namespace WCFRestfulService
{
    public class RestfulService : IRestfulService
    {
        public string GetData()
        {
            return "WCF 4.0 has introduced
            a new property \"automaticFormatSelectionEnabled\"";
        }
    }
}

There is nothing special I did, just implemented IRestfulService interface and return a string.

Here is very key part for enabling the Automatic formate, we have Three different ways to enable the automaticFormatSelectionEnabled ,

  1. Using Coding with ServiceHost object we can enable it.
  2. Using webhttp behavior option
  3. Using the standard endpoints

I am going with standard endpoints, because in standard endpoints we don’t need to configure each and every attribute , it has already configured the some attribute build in , so here is the configuration

As we can see in the above, I have commented behavior and serviceHostEnviroment tag, because we don’t need to service metadata and I have add the standard endpoint with “automaticFormatSelectionEnabled” attribute with value true.

That’s it, we have made a restful service and we can get the JSON or XML format by using single operation.

Now we have to put code at jqueryPage.htm page , here is the code of the page

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <style type="text/css">
        ul{
            border:1px solid black;
            overflow:hidden;
            width:270px;
        }
        li {
            list-style-type:none;
            float:left;
            padding:5px;        
        }
    </style>
    <script src="Scripts/jquery-1.6.1.min.js" type="text/javascript"></script>
    <script type="text/javascript">

        $(function () {

            // javascript object for getting all the jquery objects
            var pageElements = {
                actionButton: $('#btnAction'),
                xmlRadio: $('#rdoXml'),
                jsonRadio: $('#rdoJson'),
                xmlLabel: $('#lblGetXml'),
                jsonLabel: $('#lblGetJson'),
                isXML: true,
                dataTypeValue: 'XML'                
            };

            // set the button value on page load
            SetButtonValue(pageElements.xmlRadio, pageElements.xmlLabel,
                           pageElements.actionButton);

            //click event of xml radio button
            pageElements.xmlRadio.bind('click', function () {
                pageElements.isXML = true;
                SetButtonValue(pageElements.xmlRadio, pageElements.xmlLabel,
                           pageElements.actionButton);
            });

            //click event for json radio button
            pageElements.jsonRadio.bind('click', function () {
                pageElements.isXML = false;
                SetButtonValue(pageElements.jsonRadio, pageElements.jsonLabel,
                           pageElements.actionButton);
            });

            //click event of the action button
            pageElements.actionButton.bind('click', function () {

                if (!pageElements.isXML) {
                    pageElements.dataTypeValue = 'JSON';
                } else {
                    pageElements.dataTypeValue = 'XML';
                }

                //jquery ajax method for getting the result
                $.ajax({
                    type: 'GET',
                    url: '/WCFRestfulService/RestfulService.svc/data',
                    contentType: 'application/json; charset=utf-8',                    
                    dataType: pageElements.dataTypeValue,
                    processdata: true,
                    success: function (msg) {                        
                        AjaxSuccess(msg, pageElements.isXML);
                    },
                    error: function (msg) {
                        alert(msg.error);
                    }
                });
            });
        });

        //it will call when the ajax hit successful
        function AjaxSuccess(result,isXML) {
            if (isXML) {
                alert($(result).find('string').text());
            } else {
                alert(result);
            }
        }

        //set button value on click on radio buttons
        function SetButtonValue(elem,label,button) {
            var buttonAction = $('#btnAction');
            if (elem.is(':checked')) {
                button.val(label.text());
            }
        }
    </script>
</head>
<body>    
    <div>
        <ul>            
            <li>
                <input type="radio" name="rdobutton" id="rdoXml"
                 value="Get XML" checked="checked" /></li>
            <li id="lblGetXml">Get XML</li>

            <li>
                <input type="radio" name="rdobutton" id="rdoJson"
                 value="Get JSON" /></li>
            <li id="lblGetJson">Get JSON</li>
        </ul>
        <input type="button" id="btnAction" value="" />
    </div>
</body>
</html>

I have created two radio buttons and a input button, when we hit the button it will call the jquery ajax method and check the pageElements.isXML Boolean value, if its false than JSON format called otherwise XML. For getting the proof i am using firebug, here is the result of firebug when we check radio button with Get XML and Get JSON.

I hope so you enjoyed the post , please give me your valuable feedback. It will give me support to write more valuable things.

Download Demo

Categories: Jquery, WCF

Standard Endpoints in WCF 4.0

As we know that when we work with WCF, we always define the endpoint at server side and client side, both of endpoint must be same for making the communication channel between them. As we know that there are at least three attributes for making endpoint, Address, Binding and Contract, and Contract is the way where you define your service operations for external world but in some cases I have seen in WCF 3.5 we have already Contracts such as IMetadataExchange which are not implemented in our service, but its implementation is handled by WCF and similarly when we used WebHttpEndpoint for REST, it must need to configure some specific behavior. Its means we need to way where we have already define their default values and which should be re-usable. As per the need WCF 4.0 has come with the concept of Standard Endpoints which give the support that don’t need to define each and every attribute of the endpoints, it has already configured some of its properties.  Standard endpoints can be used for infrastructure and application endpoints.

Infrastructure Endpoints

Infrastructure Endpoints means that some of endpoints properties have already been configured and we don’t have rights to configure them with alternative values such that IMetadataExchange, when we using the mexHttpBinding for getting the meta data, we don’t have any other alternative options for Contract, we must be used IMetadataExchange and it can’t be changed while we are able to define its binding and address properties. However we are not implementing IMetadataExchange and as I said at above its implementation is handled by WCF. We can identify the infrastructure endpoints by using the property IsSystemEndpoint.

Application Endpoints

Application Endpoints give support to build standard endpoints, its means we can define endpoints with default values, some of properties can be changed and some of static property cannot be changed. For making the application endpoint we have to drive the class from ServiceEndpoint.

In my next post I will show practical example.

Categories: WCF
%d bloggers like this: