REST and JSON in WCF

Preview:

DESCRIPTION

REST and JSON in WCF. It is possible to implement and access REST services in WCF And still doing it object oriented This is a short presentation on how to do it in WCF If you a more detailed presentation, there is one from Mix 09 here , or you can find it in this session’s folder . - PowerPoint PPT Presentation

Citation preview

1

REST and JSON in WCF

• It is possible to implement and access REST services in WCF• And still doing it object oriented

• This is a short presentation on how to do it in WCF

• If you a more detailed presentation, there is one from Mix 09 here, or you can find it in this session’s folder.

• It takes 75 minutes

2

First a common soap service:The data object (really doesn't matter her)using System.Runtime.Serialization;namespace Data{ [DataContract] public class Person { [DataMember] public int Id { get; private set; } [DataMember] public string FirstName { get; set; } [DataMember] public string LastName { get; set; } [DataMember] public int Age { get; set; } public static Person[] GetTestPersons(int num) { Person[] result = new Person[num]; for (int i = 0; i < num; i++) result[i] = new Person { Id=(i+1) , FirstName = ""+(char)('a' + i) , LastName = ""+(char)('A' + i), Age = i * 10 }; return result; } }}

3

First a common soap service:The interface

using System.ServiceModel;using Data;

namespace WcfRestService{ [ServiceContract] public interface IPersonService { [OperationContract]

Person GetPerson(int id);

[OperationContract] Person[] GetPersons();

}}

4

First a common soap service:The class

using System;using Data;

namespace WcfRestService{ public class PersonService : IPersonService { Person GetPerson(int id) {

return Person.GetTestPersons(id)[id-1]; } public Person[] GetPersons() { return Person.GetTestPersons(5); //Q&D dev. } }}

5

First a common soap service:The interesting parts of the config file

<services> <service name="WcfRestService.PersonService">

<endpoint address="" binding="wsHttpBinding"

contract="WcfRestService.IPersonService"> <identity> <dns value="localhost"/> </identity> </endpoint> <endpoint address="mex" binding="mexHttpBinding"

contract="IMetadataExchange"/> <host> <baseAddresses> <add baseAddress="http://localhost:8732/WcfRestService/"/> </baseAddresses> </host> </service> </services> <behaviors> <serviceBehaviors> <behavior> <serviceMetadata httpGetEnabled="True"/>

</behavior> </serviceBehaviors>

6

Enable Rest in the serviceFirst the interface• Add WebGet or WebInvoke attributes to the contract• WebGet handles http GET and WebInvoke handles POST• Unfortunately can only strings be handled as parameters

using System.ServiceModel;using System.ServiceModel.Web;using Data;

namespace WcfRestService{ [ServiceContract] public interface IPersonService { [OperationContract] [WebGet(UriTemplate = "Persons/Id/{id}")] Person GetPerson(string id); //Parameter changed to string [OperationContract] [WebGet(UriTemplate = "Persons")] Person[] GetPersons(); }}

7

Enable Rest in the serviceThe class• We add a method with the string parameter• Gives the option to use two different interfaces

(left as an exercise)

public class PersonService : IPersonService { public Person GetPerson(string strId) { int id = Convert.ToInt32(strId); return this.GetPerson(id); } public Person GetPerson(int id) { return Person.GetTestPersons(id)[id - 1]; } public Person[] GetPersons() { return Person.GetTestPersons(5); } }

8

Enable Rest in the serviceThe config file• Add a new endpoint and a new behavior

.... <endpoint address="rest" binding="webHttpBinding"

contract="WcfRestService.IPersonService" behaviorConfiguration="webHttp"/>

....

.... <behaviors>.... <endpointBehaviors> <behavior name="webHttp"> <webHttp/> </behavior> </endpointBehaviors> </behaviors>....

9

Service can be accessed by the browser

10

A Rest client

• It is not possible (yet?) for VS to automatically generate a proxy for a service that is not made with the WCF Service template.

• You need an interface with the contract (could be the same as on the server, but not necessary)

• Use the contract to get a reference to an object of a class that implements the interface, which is a proxy

• Use the proxy to call services

The point here is that WCF generates the proxy from the attributtes [...] on the interface. But you have to find and insert the information in the attributes

11

The client side interfaceConnect methods with url’s using WebGet(UriTemplate)using System.ServiceModel;using System.ServiceModel.Web;using Data;

namespace WcfRestService{ [ServiceContract] public interface IPersonService { [OperationContract] [WebGet(UriTemplate = "Persons/Id/{id}")] Person GetPerson(string id);

[OperationContract] [WebGet(UriTemplate = "Persons")] Person[] GetPersons(); }}

12

The clientConnect to the service.

using System;using System.ServiceModel.Web;using Data;using WcfRestService;namespace RestClient{ class Program { static void Main(string[] args) { WebChannelFactory<IPersonService> cf =

new WebChannelFactory<IPersonService>(new Uri("http://localhost:8732/WcfRestService

/rest")); IPersonService channel = cf.CreateChannel(); Person[] persons = channel.GetPersons(); foreach (Person p in persons) Console.WriteLine("{0}\r\n{1}", p.FirstName

+" "+p.LastName, p.Age);}}}

From here: Business as usual

13

Another RESTful application

• Use it now

14

JSONfrom www.json.org

• JSON (JavaScript Object Notation) is a lightweight data-interchange format.

• It is easy for humans to read and write. • It is easy for machines to parse and generate. • It is based on a subset of the JavaScript Programming Language,

Standard ECMA-262 3rd Edition - December 1999. • JSON is a text format that is completely language independent but

uses conventions that are familiar to programmers of the C-family of languages, including C, C++, C#, Java, JavaScript, Perl, Python, and many others.

• These properties make JSON an ideal data-interchange language.

15

JSONfrom www.json.org

• JSON is built on two structures:

‒ A collection of name/value pairs. In various languages, this is realized as an object, record, struct, dictionary, hash table, keyed list, or associative array.

‒ An ordered list of values. In most languages, this is realized as an array, vector, list, or sequence.

• These are universal data structures. Virtually all modern programming languages support them in one form or another.

• It makes sense that a data format that is interchangable with programming languages also be based on these structures.

16

Examples

From MagicEightBall:{"d":"Is this JSON? Yes"}

From Person example (the GetPersons() service):[{"Age":0,"FirstName":"a","Id":1,"LastName":"A"},{"Age":10,"FirstName":"b","Id":2,"LastName":"B"},{"Age":20,"FirstName":"c","Id":3,"LastName":"C"},{"Age":30,"FirstName":"d","Id":4,"LastName":"D"},{"Age":40,"FirstName":"e","Id":5,"LastName":"E"}]

17

Extend the person example with JSON

• Two alternatives: ‒ Access it like in Rest‒ Access it like in SOAP (I believe)

18

1st alternative• We'll use some annotations, therefore we need a new interface,

which is quite similar to the previous one [ServiceContract] public interface IPersonServiceJSON { [OperationContract] [WebGet(UriTemplate = "Persons/Id/{id}",

ResponseFormat = WebMessageFormat.Json)] Person GetPerson(string id);

[OperationContract] [WebGet(UriTemplate = "Persons",

ResponseFormat = WebMessageFormat.Json)] Person[] GetPersons(); }public class PersonService:IPersonService,IPersonServiceJSON{...} //Remember to implement the interface

19

Add a new endpoint

• Could have reused webhttp, but now it is explicit marked for json

<endpoint address="json" behaviorConfiguration="jsonBehave"

binding="webHttpBinding"

contract="WcfRestService.IPersonServiceJSON"/>...<behavior name="jsonBehave"> <webHttp/></behavior>

20

How to call it

• Just put in the URL, e.g. http://localhost:8732/WcfRestService/json/persons

• If you do it in the browser you will be asked to save a file. Save it as a txt file. Then you can see it in an editor

21

2nd alternative• Change the interface and config from 1st alternative to: [ServiceContract] public interface IPersonServiceJSON { [OperationContract] [WebGet] Person GetPerson(string id);

[OperationContract] [WebGet] Person[] GetPersons(); }

<behavior name="jsonBehave"><enableWebScript/>

</behavior>

http://localhost:8732/WcfRestService/json/GetPerson?id=5

22

Snippets of AJAXFull example in folder

• Get an object for sending server requests<script language="javascript" type="text/javascript"> function makeCall(operation) { var xmlHttp; try { xmlHttp = new XMLHttpRequest(); } catch (e) { try { xmlHttp = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) { alert("This sample only works in browsers with AJAX"); return false; } } }

23

React when state changes in http

xmlHttp.onreadystatechange = function() { if (xmlHttp.readyState == 4) { //Finished receiving if (xmlHttp.status == 200) { //Response: OK

//Get the response (result) var result = eval('(' + xmlHttp.responseText + ')');

//Unsafe way of evaluating JavaScript. It can be injected document.getElementById("result").innerHTML = result.d; } else alert(xmlHttp.status); //Not OK document.getElementById("jsonText").innerHTML =

xmlHttp.responseText; } }

24

Send request with get or post

var url = "http://localhost:8080/MagicEightBallService/json/"; url = url + operation;

var params = '{"userQuestion":"'; params = params + document.getElementById("question").value; params = params + '"}';

if (readRadioButton("MethodRadio")=="GET") url=url+"?userQuestion="

+document.getElementById("question").value; xmlHttp.open(readRadioButton("MethodRadio"), url, true); xmlHttp.setRequestHeader("Content-type", "application/json"); xmlHttp.send(params); }

26

Exercise (optional)

• Make a web service for the bank.• Start by making a soap based ws.• And then add a rest based

Recommended