Professional Documents
Culture Documents
REST is not a standard but an approach (specification) to developing and providing services on the internet. REST follows an architectural style of web application, like a user progressing through a web application by selecting links which takes him to the next page. REST is based on Resources that are identified by a unique URI. When we conform to the standard or characteristic defined for a service to be REST, we can refer the service to be RESTful. REST does not tie itself to any particular platform, but is currently done on Web with HTTP.
Stateless
Each request to the server should contain all the information required to understand and complete the request.
Cacheable
The data within a response to a request should be cacheable/ non-cacheable to be used by client at another point of time. This might improve the performance and reduce network traffic.
Layered System
Intermediary servers like Proxy servers or Cache servers can be used to improve performance or introduce security.
Uniform Interface
A uniform interface (like HTTP GET, POST, DELETE, PUT) is to be used to access a resource. A RESTful Web Service is a collection of the following:
URI
Uniform Resource Identifier - This is a unique way of identifying resources on the network. Every resource on the web is given a unique identifier - a universal identifier (example, URL). All web browsers, servers, applications understand this identifier, which makes it easy to connect and exchange information between one another without any issues.
MIME Type
Can be XML, HTML, and JSON.
HTTP Methods
HTTP forms a standard way to communicate with resources on the web. GET, PUT, DELETE, POST are some of the common methods to access a resource.
GET
Helps to request a specific representation of the resource.
PUT
Updates a resource with a specific representation.
DELETE
Deletes a specified resource.
POST
Creates a new resource.
provided a REST template which we can use to create new projects, this will create a basic skeleton code for REST. From VS 2010, create a new project, select an online template, and WCF. There are various options displayed, select "WCF REST Service Template 40". Create a class which returns a collection of employee details. Mark the method which we want to call with the attribute[WebGet()].
Collapse | Copy Code
[ServiceContract] [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)] // NOTE: If the service is renamed, remember to update the global.asax.cs file public class Service1 { // TODO: Implement the collection resource // that will contain the SampleItem instances [WebGet(UriTemplate = "")] public IList<EmployeeDetail> GetEmployeeDetail() { IList<EmployeeDetail> employeeDetail = new List<EmployeeDetail>(); EmployeeDetail empDetail1 = new EmployeeDetail(); empDetail1.EmployeeIdentifier = 123; empDetail1.EmployeeName = "Test1"; empDetail1.ProjectName = "NE"; employeeDetail.Add(empDetail1); EmployeeDetail empDetail2 = new EmployeeDetail(); empDetail2.EmployeeIdentifier = 1234; empDetail2.EmployeeName = "Test2"; empDetail2.ProjectName = "NE"; employeeDetail.Add(empDetail2); return employeeDetail; } } public class EmployeeDetail { private string employeeName; private int employeeId; private string projectName; public int EmployeeIdentifier { get { return employeeId; } set { employeeId = value; } } public string EmployeeName { get
{ return employeeName; } set { employeeName = value; } } public string ProjectName { get { return projectName; } set { projectName = value; } } }
Build and run the code. Now access the URL http://localhost:8422/Service1/. The following XML is returned from the service:
Collapse | Copy Code
<ArrayOfEmployeeDetail xmlns="http://schemas.datacontract.org/2004/07/WcfRestService2" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> <EmployeeDetail> <EmployeeIdentifier>123</EmployeeIdentifier> <EmployeeName>Test1</EmployeeName> <ProjectName>NE</ProjectName> </EmployeeDetail> <EmployeeDetail> <EmployeeIdentifier>1234</EmployeeIdentifier> <EmployeeName>Test2</EmployeeName> <ProjectName>NE</ProjectName> </EmployeeDetail> </ArrayOfEmployeeDetail>
Security of the end point is set by the Security property of WebHttpBinding. The Security property is of typeWebHttpSecurity and is used to determine the security mode required by the binding and the type of client credentials it requires. There are two properties of WebHttpSecurity: Mode (of type WebSecurityHttpMode) andTransport (of type HttpTransportSecurity). There are three levels of security that can be specified usingWebHttpSecurityMode: 1. 2. 3.
ClientCredentialType (of type HttpClientCredentialType) ProxyCredentialType (of type HttpProxyCredentialType) Releam (String)
Values for HttpClientCredentialType can be any one of the following: None, Basic, Digest, NTLM, Windows,Certificate.
Authorization
Once authenticated, the next step is to authorize the client, what they can do and what they can't do. 1. Impersonation: by impersonating the client, the authorization is delegated to another layer. For example, when a client is trying to insert or update data in to a SQL Server database, SQL Server throws an exception in case the client doesn't have permission, which can be bubbled back to the client. Role based: Implement authorization by restricting access to operations to certain Windows users or groups.
2.
Advantages of REST
Services offered by REST style are easier to consume compared to other style services, meaning lower learning curve for the consumer. Supports caching of URI of the service. Components can be deployed independently. Lightweight (consider SOAP which uses WSDL which makes the SOAP protocol a complex service). Simple clients.
Disadvantage of REST
The major disadvantage from a developer's perceptive is it does not have metadata. So it requires knowledge of implementation details. On the security aspect, RESTful services depend on the security aspect of HTTP security.
**************************
WCF
Windows Communication Foundation (WCF) is Microsofts combined programming model for building service-oriented architecture (SOA). Using this, the developer can build a secure, reliable, transacted solutions across platforms. WCF supports concentrated computing where services have isolated consumers. Clients can consume multiple services as well as services can be consumed by multiple clients. For creating basic application in WCF, please refer to the article Introduction of Window Communication Foundation. Web Services WCF Services
Web Services Web services were developed for building applications that send and receive messages by using the Simple Object Access Protocol (SOAP) over HTTP. The structure of the messages can be defined using an XML Schema, and a tool is provided to facilitate serializing the messages to and from .NET Framework objects. The technology can automatically generate metadata to describe Web services in the Web Services Description Language (WSDL)
WCF Services
WCF services were developed for building applications to send and receiv formats and conveyed by using any transport protocol. Simple Object Acc by default format.The structure of the messages can be defined using an various options for serializing the messages to and from .NET Framework automatically generate metadata to describe applications built using the also provides a tool for generating clients for those applications from the
Support for sending messages using not only HTTP, but also TCP and oth ability to switch message protocols with minimal effort. Support for hostin than a Web server. Built-in support for the latest Web services standards ability to easily support new ones. Support for security, transactions and r messages using formats other than SOAP.
XmlSerializer
ASP.NET relies on the XmlSerializerto translate data represented by .NET Framework types to XML for transmission to or from a service and to translate data received as XML into .NET Framework objects. Defining the complex data types that an ASP.NET service is to use requires the definition of .NET Framework classes that theXmlSerializer can serialize to and from XML. The XmlSerializer and the attributes of theSystem.Xml.Serialization namespace are designed to allow you to map .NET Framework types to any valid type defined in XML Schema, and so they provide for very precise control over how a type is represented in XML. Lesser performance compared with WCF DataContractSerializer. The attributes for use with theXmlSerializer do not indicate which fields or properties of the type are serialized into XML. The XmlSerializer can only translate the public members of a .NET object into XML.
DataContractSerializer
The DataContractAttribute signifies that zero or more of a types f serialized, while theDataMemberAttribute indicates that a particular f serialized. The DataContractAttributecan be applied to a class or st TheDataMemberAttribute can be applied to a field or a property, and which the attribute is applied can be either public or private. Instanc the DataContractAttribute applied to them are referred to as data serialized into XML using DataContractSerializer.
The DataContractSerializer,DataContractAttribute and Dat very little control over how a type is represented in XML. You can only spe names used to represent the type and its fields or properties in the XML, the fields and properties appear in the XML. Everything else about the str represent the .NET type is determined by theDataContractSerialize control over how a type is to be represented in XML, the serialization proc predictable for theDataContractSerializer, and, thereby, easier to o
A practical benefit of the design of theDataContractSerializer is b approximately ten percent better performance.
or properties are serialized. Therefore, data contracts are explicit contract data that an application is to send and receive.
The DataContractSerializer can translate the members of objects access modifiers of those members.
Instances of collection classes can be serialized The DataContractSerializer is much more likely to be able to seria into XML only if the classes implement either existing .NET type into XML without having to either modify the definition the IEnumerable orICollection interface. wrapper for it.
Web Services Classes that implement theIDictionary interface, such asHashtable, cannot be serialized into XML.
WCF Services
It can translate into XML types like Hashtable that implement the IDic
XmlSerializer does not support versioning. The DataContractSerializer incorporates some support for version
semantically identical to the XML. defined.
XmlSerializer serializes a type by default is DataContractSerializer serializes a type, provided the namespace
It works based on the Remote Procedural Call It is working with HTTP's uniform interface (RPC) Service Reference has to add in the client applications No need to add the service reference in the client applications
Step 2
Delete the existing IService1.cs & Service1.svc files and create two new files, IRESTService.cs & RESTService.cs.
Step 3
Create the person entity in the IService.cs (it can be created separately) and write a simple member for this entity. ForDataContractSerialization decorate this class and member with DataContract & DataMember attributes. See the code below:
Collapse | Copy Code
[DataContract] public class Person { [DataMember] public string ID; [DataMember] public string Name; [DataMember] public string Age; }
Person class and its members decorated with [DataContract] & [DataMember] usingSystem.Runtime.Serialization namespace.
[DataContract] An entity class which can be DataContractSerializable over the network. [Datamember] Only decorated with [Datamember] property can be serializable & also property of the class must be decorated with [DataContract]
Step 4
Create methods in IRESTService class and interface decorated with [ServiceContract] & its members decorated with [OperationContrat] using System.ServiceModel namespace.
Collapse | Copy Code
[ServiceContract] public interface IRestSerivce { [OperationContract] Person CreatePerson(Person createPerson); [OperationContract] List<person> GetAllPerson();
[OperationContract] Person GetAPerson(string id); [OperationContract] Person UpdatePerson(string id, Person updatePerson); [OperationContract] void DeletePerson(string id); }
[ServiceContract] - A service contract exposes class or interface to the client applications, which may contain one or more [OperationContract] methods. [OperationContract] - Indicates that a method defines an operation that is part of a service contract in an application, i.e., only the method decorated with [OperationContract] is visible for WCF client application and class of this method must be decorated with [ServiceContract].
Step 5
Up to this level, code is similar to that normal WCF services, RESTful services works under HTTP protocol, as there is two important attributes WebGet & WebInvoke (System.ServiceModel.Web namespace) has to include for making this application as RESTful service.
[ServiceContract] public interface IRestSerivce { //POST operation [OperationContract] [WebInvoke(UriTemplate = "", Method = "POST")] Person CreatePerson(Person createPerson); //Get Operation [OperationContract] [WebGet(UriTemplate = "")] List<person> GetAllPerson(); [OperationContract]
[WebGet(UriTemplate = "{id}")] Person GetAPerson(string id); //PUT Operation [OperationContract] [WebInvoke(UriTemplate = "{id}", Method = "PUT")] Person UpdatePerson(string id, Person updatePerson); //DELETE Operation [OperationContract] [WebInvoke(UriTemplate = "{id}", Method = "DELETE")] void DeletePerson(string id); }
Please see the modified code for IRESTService interface, WebGet & WebInvoke attributes decorates for methods available in the IRESTService interface.
Collapse | Copy Code
Person CreatePerson(Person createPerson); //It is basically insert operation, so WebInvoke HTTP POST is used List<person> GetAllPerson(); Person GetAPerson(string id); //These two methods retrieve the information, so WebGet (HTTP Get) is used Person UpdatePerson(string id, Person updatePerson); //This method updates the available information, so WebInvoke HTTP PUT is used void DeletePerson(string id); //This method deletes the available information, //so WebInvoke HTTP DELETE is used
Step 6
Implement the IRESTService in the RESTService class and complete the business requirements. Please see the sample code below:
Collapse | Copy Code
public class RestSerivce : IRestSerivce { List<person> persons = new List<person>(); int personCount = 0; public Person CreatePerson(Person createPerson) { createPerson.ID = (++personCount).ToString(); persons.Add(createPerson); return createPerson; } public List<Person> GetAllPerson() { return persons.ToList(); }
public Person GetAPerson(string id) { return persons.FirstOrDefault(e => e.ID.Equals(id)); } public Person UpdatePerson(string id, Person updatePerson) { Person p = persons.FirstOrDefault(e => e.ID.Equals(id)); p.Name = updatePerson.Name; p.Age = updatePerson.Age; return p; } public void DeletePerson(string id) { persons.RemoveAll(e => e.ID.Equals(id)); } }
Step 7
We have to make this service able to be run in ASP.NET compatibility mode, for thisAspNetCompatibilityRequirements attributes have to decorate with the RESTService class.
Collapse | Copy Code
[AspNetCompatibilityRequirements (RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)] public class RESTSerivce : IRestSerivce { //Code Implementation //. . . . . . // . . . . . . }
In the above RESTService class additionally decorated with ServiceBehavior attribute, it specifies internal behavior of a service operation.
Step 8
For using this RESTFul service application, this service has to host. So we need to be done below modification for running the RESTService.
<serviceHostingEnvironment aspNetCompatibilityEnabled="true">
</serviceHostingEnvironment> <standardEndpoints> <webHttpEndpoint> <standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true"></standardEndpoint> </webHttpEndpoint> </standardEndpoints> </system.serviceModel>
<serviceHostingEnvironment> tag helps to run the applications in ASP.NET compatibility mode.<standardEndpoints> tag helps to get WebHelp for the RESTFul application.
Step 9
Run the RESTFulDemo application, it will be open in the explorer and address bar contain the base address ofRESTFulDemo service. http://localhost:XXXX/ Type the Routingprefix name RestService (string value given in the global.asax file). http://localhost:XXXX/RestService - It is basically URI of the Get operation.
Still we saw about creating and hosting the RESTFul services, next we have to consume this service, therefore we will see basic application to consume this RESTFulDemo service.
Step 2
Collapse | Copy Code
Console.WriteLine("Enter Method:"); string Method = Console.ReadLine(); Console.WriteLine("Enter URI:"); string uri = Console.ReadLine(); HttpWebRequest req = WebRequest.Create(uri) as HttpWebRequest; req.KeepAlive = false; req.Method = Method.ToUpper(); if (("POST,PUT").Split(',').Contains(Method.ToUpper())) { Console.WriteLine("Enter XML FilePath:"); string FilePath = Console.ReadLine(); content = (File.OpenText(@FilePath)).ReadToEnd(); byte[] buffer = Encoding.ASCII.GetBytes(content); req.ContentLength = buffer.Length; req.ContentType = "text/xml"; Stream PostData = req.GetRequestStream(); PostData.Write(buffer, 0, buffer.Length); PostData.Close(); } HttpWebResponse resp = req.GetResponse() as HttpWebResponse; Encoding enc = System.Text.Encoding.GetEncoding(1252); StreamReader loResponseStream = new StreamReader(resp.GetResponseStream(), enc); string Response = loResponseStream.ReadToEnd(); loResponseStream.Close(); resp.Close(); Console.WriteLine(Response); } catch (Exception ex) { Console.WriteLine(ex.Message.ToString()); } Console.WriteLine(); Console.WriteLine("Do you want to continue?"); } while (Console.ReadLine().ToUpper() == "Y");
Step 3
Before running the RESTFulDemo application, set multiple startup projects. Please see the below image:
RUN the application. It will run the RESTFulDemo service as well as RESTClient console application.
This operation creates a new person entity in the service, it can be seen in the browser by HTTP Get operation.
In the above screen, call the URI http://localhost:XXXX/restservice/1, URI ends with person ID (1). It calls the service operation.
Collapse | Copy Code
So it retrieves the person with ID 1. Please refer to the attached project for detailed code. Fiddler tool is more useful to test the RESTFul services.
Conclusion
I hope this article helps you to understand basic concept of RESTFul and that the reader is able to code to create & consume RESTFul service. Please let me know your valuable comments.
What about interoperability? Isn't SOAP supposed to be about interoperability? Isn't SOAP more interoperable than REST?
If you define interoperability as the technical ability to communicate between two divergent endpoints, I assert that REST wins the interoperability battle hands down. Since one of the driving points behind creating the SOAP specification was to create an interoperable way to communicate between different platforms and different languages, many people are surprised by this assertion. But a funny thing happened on the way to widespread interoperability: the WS-* specifications (and vendors' implementations of said specifications) made SOAP services less interoperable rather than more interoperable. The problem in the SOAP and WS-* arena is the large number of different standards (and versions of each of those standards) to choose from. And when a particular vendor chooses to implement a particular standard, that vendor often provides an implementation that is just slightly different from another vendor's (or all others). This leads to problems whenever you have to cross vendor boundaries (languages and operating system). Of course, even to use SOAP you need a SOAP toolkit on your platform, which most (but not all) platforms have today. And then you have to deal with myriad WS-* specifications and figure out which to use (or not to use) and how that affects interoperability. To be honest, it's kind of a mess out there. In terms of platforms, REST has the advantage because all you need to use REST is an HTTP stack (either on the client or the server). Since almost every platform and device has that today, I would argue that REST has the widest interoperability. Given that mobile devices, household devices, POS devices, DVD players, and TVs all have Internet connectivity, there are more and more platforms for which having a full SOAP toolkit is impossible or unlikely. And even if you do have a SOAP toolkit for a particular platform, the chance of it working with another platform's implementation is not 100%.
But what about metadata? So what if REST is so interoperablethere's no WSDL with REST, and without WSDL, I can't generate a client-side proxy to call a service. REST is hard to use.
It's true that in the world of REST, there is no direct support for generating a client from server-side-generated metadata, as there is in the world of SOAP with Web Service Description Language (WSDL). A couple of efforts are being made to get such support into REST, one being a parallel specification, known as WADL (Web Application Description Language). The other is a push to use WSDL 2.0 to describe RESTful endpoints. I often say that REST is simple, but simple doesn't always mean easy. SOAP is easy (because of WSDL), but easy doesn't always mean simple. Yes, using WSDL makes generating a proxy for a SOAP-based service easier than writing the code to call a RESTful service. But once you generate that proxy, you still have to learn the API. Nothing in the WSDL tells you which method to call first or second or whether you need to call the methods in any particular order at all. These are all things you need to figure out after you generate the proxy and are prototyping the code to use the service. Building a client against a RESTful service means you are learning the service and how it works as you build the client. Once you have finished, you have a complete understanding of the service, its resources, and the interaction you can have with those resources. To me, this is a big benefit. Since RESTful services follow the constraints of REST (at least they are supposed to), there is a convention that you can easily follow as you determine the different parts of the service. Also, out in the wilds of developer-land, most services are wrapped in something often called a "service agent," which is another layer of indirection to protect clients from changes in the service layer. This may be needed in either REST or SOAP. Another point is that metadata-generated proxies are part of what SOAP was meant to get away from in the RPC era, namely local-remote transparency. The concept of having an API on the client that matches the API on the server was considered to be a bad idea, but that's exactly what happens in most SOAP-based services. Having a metadata-generated proxy in REST also reduces the chances of taking advantage of hyperlinking. Using hypertext as the engine of application state (HATEOAS) is one of the constraints of REST, and using it requires a more loosely coupled client API. The last point I'll make is that as support for REST becomes more ubiquitous, building clients will get easier and easier. If you look at the Windows Communication Foundation (WCF) REST starter kit, it includes facilities that head in this direction. The new HttpClient API makes using HTTP much easier than using the .NET WebRequest/WebResponse API. Also, there is a new Paste as XML Serializable tool, which allows you to copy a piece of XML (say from the documentation of a RESTful endpoint) and generate a .NET type that can represent that XML instance in your application. This is similar to what the WCF tools do automatically for the whole service with WSDL. Over time, these tools will become much more sophisticated, further simplifying the client experience in WCF when using RESTful services.
After all that information, aren't you telling me that REST is good for Internet-facing applications, and SOAP for enterprise applications?
If you've read the rest of this column, you can probably imagine that I think this statement is generalized and false. Often I hear this sentiment after discussing the lack of explicit distributed transaction support in REST versus the explicit support in WS-Atomic Transactions. My retort is generally something like "Well, ASP.NET doesn't have support for distributed transactions, but does that mean ASP.NET isn't useful for enterprises?" My point is that not every technology solves every problem, and there are plenty of technologies that don't support the typical features people think of when they think of enterprises but that are incredibly helpful for enterprises nonetheless. In fact, when I think of enterprise applications, I often think of speed and scalability scalability being one of the main differences between REST and SOAP. SOAP services are much harder to scale than RESTful services, which is, of course, one of the reasons that REST is often chosen as the architecture for services that are exposed via the Internet (like Facebook, MySpace, Twitter, and so on). Inside enterprises, applications also often need to scale as well. Using REST means that you can take advantage of HTTP caching and other features, like Conditional GET, that aid in scaling services. Many of these techniques can't be used with SOAP because SOAP uses POST only over HTTP.
Bottom Line
I hope that after you read this column, you'll think that the answer to "Which is better, REST or SOAP?" is "It depends." Both the REST architectural style and SOAP and the WS-* protocols have advantages and disadvantages when it comes to building services. Those of us in the RESTafarian camp (yes, I must give full disclosure here: I am definitely in that camp) believe that for most service situations, REST provides more benefits than SOAP or WS-*. On the other hand, SOAP and WS-* have some features that are easy (and possible) to implement using REST. When you need those specific features, you definitely want to use runtimes and toolkits that can provide those features. Although this column wasn't specifically about WCF, one nice feature of adopting WCF is that it supports both REST and SOAP/WS-*. Moving back and forth between the two worlds becomes easier if you have one programming and runtime model to learn.
Introduction
When SOAP is believed to be overkill, some developers may choose RESTful services. REST (Representative State Transfer) is mostly used when developers need high range of interoperability and when trying to restrict themselves to basic XML messages or JSON that are transmitted over HTTP. RESTful services are fundamentally different from SOAP-based services because they don't attempt to achieve transport neutrality. In fact, RESTful services typically embrace HTTP as the only transport used throughout the system. Using REST, developers can model their services as resources and give these resources unique identifiers in the form of URIs. In this article, we will take an existing SOAP-based service and convert it over to a more RESTful design.
Background
namespace SoapToRESTfullDemo { [ServiceContract] public interface IProductService { [OperationContract] List<ProductEntity> GetAllProducts(); [OperationContract] ProductEntity GetProductByID(int productID); [OperationContract] bool UpdateProduct(ProductEntity product); } [ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)] public class ProductService : IProductService { #region IProductService Members public List<ProductEntity> GetAllProducts() { List<ProductEntity> products = new List<ProductEntity>(); ProductEntity productEnt = null; using (var NWEntities = new NorthwindEntities()) { List<Product> prods = (from p in NWEntities.Products select p).ToList(); if (prods != null) { foreach (Product p in prods) { productEnt = new ProductEntity() { ProductID = p.ProductID, ProductName = p.ProductName, QuantityPerUnit = p.QuantityPerUnit, UnitPrice = (decimal)p.UnitPrice, UnitsInStock = (int)p.UnitsInStock,
ReorderLevel = (int)p.ReorderLevel, UnitsOnOrder = (int)p.UnitsOnOrder, Discontinued = p.Discontinued }; products.Add(productEnt); } } } return products; } public ProductEntity GetProductByID(int productID) { ProductEntity productEnt = null; using (var NWEntities = new NorthwindEntities()) { Product prod = (from p in NWEntities.Products where p.ProductID == productID select p).FirstOrDefault(); if (prod != null) productEnt = new ProductEntity() { ProductID = prod.ProductID, ProductName = prod.ProductName, QuantityPerUnit = prod.QuantityPerUnit, UnitPrice = (decimal)prod.UnitPrice, UnitsInStock = (int)prod.UnitsInStock, ReorderLevel = (int)prod.ReorderLevel, UnitsOnOrder = (int)prod.UnitsOnOrder, Discontinued = prod.Discontinued }; } return productEnt; } public bool UpdateProduct(ProductEntity product) { bool updated = true; using (var NWEntities = new NorthwindEntities()) { var productID = product.ProductID; Product productInDB = (from p in NWEntities.Products where p.ProductID == productID select p).FirstOrDefault(); if (productInDB == null) { throw new Exception("No product with ID " + product.ProductID); } NWEntities.Products.Remove(productInDB); productInDB.ProductName = product.ProductName; productInDB.QuantityPerUnit = product.QuantityPerUnit; productInDB.UnitPrice = product.UnitPrice; productInDB.Discontinued = product.Discontinued; NWEntities.Products.Attach(productInDB); NWEntities.Entry(productInDB).State = System.Data.EntityState.Modified; int num = NWEntities.SaveChanges(); if (num != 1) { updated = false; } } return updated;
} #endregion } }
First, we need to add the ServiceModel.Web assembly which gives us access to the WebGet and WebInvoke methods. The following is the step by step instruction for converting the IProduct interface: 1. 2. 3. In the Product interface, lets define our URI mapping which specifies what URI to map to; for instance,[WebGet(UriTemplate = "products")] for the GetAllProducts method For the GetProductByID, we will need to pass in the base address, followed by the product, then followed by the productID - [WebGet(UriTemplate = "product/{productID}")] WebInvoke uses the same property. The update/submit method uses the POST method; for instance,[WebInvoke(Method = "POST", UriTemplate = "product")] Your complete code should look like the following (as you can see, the difference with SOAP-based is just around the interface):
Collapse | Copy Code
namespace SoapToRESTfullDemo { [ServiceContract] public interface IProductService { [WebGet(UriTemplate = "products")] [OperationContract] List<ProductEntity> GetAllProducts(); //UriTemplate - the base address, followed by product and followed by the ID [WebGet(UriTemplate = "product/{productID}")] [OperationContract] ProductEntity GetProductByID(string productID); //WebInvoke has the same property - for update/submit use POST. Post it to product [WebInvoke(Method = "POST", UriTemplate = "product")] [OperationContract] bool UpdateProduct(ProductEntity product); } [ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)] public class ProductService : IProductService { #region IProductService Members public List<ProductEntity> GetAllProducts() { List<ProductEntity> products = new List<ProductEntity>(); ProductEntity productEnt = null; using (var NWEntities = new NorthwindEntities()) { List<Product> prods = (from p in NWEntities.Products
select p).ToList(); if (prods != null) { foreach (Product p in prods) { productEnt = new ProductEntity() { ProductID = p.ProductID, ProductName = p.ProductName, QuantityPerUnit = p.QuantityPerUnit, UnitPrice = (decimal)p.UnitPrice, UnitsInStock = (int)p.UnitsInStock, ReorderLevel = (int)p.ReorderLevel, UnitsOnOrder = (int)p.UnitsOnOrder, Discontinued = p.Discontinued }; products.Add(productEnt); } } } return products; } public ProductEntity GetProductByID(string productID) { int pID = Convert.ToInt32(productID); ProductEntity productEnt = null; using (var NWEntities = new NorthwindEntities()) { Product prod = (from p in NWEntities.Products where p.ProductID == pID select p).FirstOrDefault(); if (prod != null) productEnt = new ProductEntity() { ProductID = prod.ProductID, ProductName = prod.ProductName, QuantityPerUnit = prod.QuantityPerUnit, UnitPrice = (decimal)prod.UnitPrice, UnitsInStock = (int)prod.UnitsInStock, ReorderLevel = (int)prod.ReorderLevel, UnitsOnOrder = (int)prod.UnitsOnOrder, Discontinued = prod.Discontinued }; } return productEnt; } public bool UpdateProduct(ProductEntity product) { bool updated = true; using (var NWEntities = new NorthwindEntities()) { var productID = product.ProductID; Product productInDB = (from p in NWEntities.Products where p.ProductID == productID select p).FirstOrDefault(); if (productInDB == null) { throw new Exception("No product with ID " + product.ProductID); } NWEntities.Products.Remove(productInDB);
productInDB.ProductName = product.ProductName; productInDB.QuantityPerUnit = product.QuantityPerUnit; productInDB.UnitPrice = product.UnitPrice; productInDB.Discontinued = product.Discontinued; NWEntities.Products.Attach(productInDB); NWEntities.Entry(productInDB).State = System.Data.EntityState.Modified; int num = NWEntities.SaveChanges(); if (num != 1) { updated = false; } } return updated; } #endregion } }
Once we have the interface modified, we can then modify the configuration file (app.config) to wire up the service. The following are the steps for modifying the app.config: 1. Change binding from basic to WebHttpBinding - <endpoint address =""
binding="wsHttpBinding" contract="SoapToRESTfullDemo.IProductService"> 2. Add a new behavior - <behavior name="SoapToRESTfullDemo.Service1Behavior"> 3. Apply this behavior to the service - <service name="SoapToRESTfullDemo.ProductService" behaviorConfiguration="SoapToRESTfullDemo.Service1Behavior">
Your app.config should look like the following:
Collapse | Copy Code
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.web> <compilation debug="true" /> </system.web> <!-- When deploying the service library project, the content of the config file must be added to the host's app.config file. System.Configuration does not support config files for libraries. --> <system.serviceModel> <services> <service name="SoapToRESTfullDemo.ProductService" behaviorConfiguration="SoapToRESTfullDemo.Service1Behavior"> <host> <baseAddresses> <add baseAddress = "http://localhost:8888/products" /> </baseAddresses> </host> <!-- Service Endpoints --> <!-- Unless fully qualified, address is relative to base address supplied above --> <endpoint address ="" binding="wsHttpBinding" contract="SoapToRESTfullDemo.IProductService"> <!-Upon deployment, the following identity element should be removed or replaced to reflect the identity under which the deployed service runs. If removed, WCF will infer an appropriate identity
automatically. --> <identity> <dns value="localhost"/> </identity> </endpoint> <!-- Metadata Endpoints --> <!-- The Metadata Exchange endpoint is used by the service to describe itself to clients. --> <!-- This endpoint does not use a secure binding and should be secured or removed before deployment --> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/> </service> </services> <behaviors> <serviceBehaviors> <behavior name="SoapToRESTfullDemo.Service1Behavior"> <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment --> <serviceMetadata httpGetEnabled="True"/> <!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information --> <serviceDebug includeExceptionDetailInFaults="False" /> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel> <connectionStrings> <add name="NorthwindEntities" connectionString="metadata=res://*/Northwind.csdl|res://*/Northwind.ssdl|res:// */Northwind.msl;provider=System.Data.SqlClient;provider connection string="data source=IDALTW76S51DS1;initial catalog=Northwind; integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" /> </connectionStrings> </configuration>
Running the REST Service We basically expose the same functionality as we did using SOAP, but these functionalities are exposed through the standard HTTP uniform service contract. The URI will determine which functionality is being invoked. Lets start by running the host. As seen in the following image, the host displays the base address, which is specified in the configuration file ( http://localhost:8080/productservice).
Now, we can see the service invocation by typing in the full address in the Web browser; such ashttp://localhost:8080/productservice/products. This address will display the following result for the GetAllProducts(remember the UriTemplate is calling for products):
When calling GetProductByID, we will need to pass in the product ID as part of the query string; for instance,http://localhost:8080/product/productID. The following is the result, which returns only a product with an ID of 1:
Definitions
REST
RESTs sweet spot is when you are exposing a public API over the internet to handle CRUD operations on data. REST is focused on accessing named resources through a single consistent interface.
SOAP
SOAP brings its own protocol and focuses on exposing pieces of application logic (not data) as services. SOAP exposes operations. SOAP is focused on accessing named operations, each implement some business logic through different interfaces. Though SOAP is commonly referred to as web services this is a misnomer. SOAP has very little if anything to do with the Web. REST provides true Web services based on URIs and HTTP. By way of illustration here are few calls and their appropriate home with commentary.
getUser(User);
This is a SOAP operation as you are performing an operation. Yes, either could be done in either SOAP or REST. The purpose is to illustrate the conceptual difference.
Why REST?
Here are a few reasons why REST is almost always the right answer. Since REST uses standard HTTP it is much simpler in just about ever way. Creating clients, developing APIs, the documentation is much easier to understand and there arent very many things that REST doesnt do easier/better than SOAP. REST permits many different data formats where as SOAP only permits XML. While this may seem like it adds complexity to REST because you need to handle multiple formats, in my experience it has actually
been quite beneficial. JSON usually is a better fit for data and parses much faster. REST allows better support for browser clients due to its support for JSON. REST has better performance and scalability. REST reads can be cached, SOAP based reads cannot be cached. Its a bad argument (by authority), but its worth mentioning that Yahoo uses REST for all their services including Flickr and del.ici.ous. Amazon and Ebay provide both though Amazons internal usage is nearly all REST source. Google used to provide only SOAP for all their services, but in 2006 they deprecated in favor of REST source. Its interesting how there has been an internal battle between rest vs soap at amazon. For the most part REST dominates their architecture for web services.
Why SOAP?
Here are a few reasons you may want to use SOAP.
WS-Security
While SOAP supports SSL (just like REST) it also supports WS-Security which adds some enterprise security features. Supports identity through intermediaries, not just point to point (SSL). It also provides a standard implementation of data integrity and data privacy. Calling it Enterprise isnt to say its more secure, it simply supports some security tools that typical internet services have no need for, in fact they are really only needed in a few enterprise scenarios.
WS-AtomicTransaction
Need ACID Transactions over a service, youre going to need SOAP. While REST supports transactions, it isnt as comprehensive and isnt ACID compliant. Fortunately ACID transactions almost never make sense over the internet. REST is limited by HTTP itself which cant provide two-phase commit across distributed transactional resources, but SOAP can. Internet apps generally dont need this level of transactional reliability, enterprise apps sometimes do.
WS-ReliableMessaging
Rest doesnt have a standard messaging system and expects clients to deal with communication failures by retrying. SOAP has successful/retry logic built in and provides end-to-end reliability even through SOAP intermediaries.
Summary
In Summary, SOAP is clearly useful, and important. For instance, if I was writing an iPhone application to interface with my bank I would definitely need to use SOAP. All three features above are required for banking transactions. For example, if I was transferring money from one account to the other, I would need to be certain that it completed. Retrying it could be catastrophic if it succeed the first time, but the response failed.
What is SOAP ?
The Simple Object Access Protocol (SOAP) is an attempt to define a standard for creating web service APIs. It is a pattern, a web service architecture, which specifies the basic rules to be considered while designing web service platforms. It typically uses HTTP as a layer 7 protocol, although this is not mandatory. The SOAP message itself consists of an envelope, inside of which are the SOAP headers and body, the actual information we want to send. It is based on the standard XML format, designed especially to transport and store structured data. SOAP may also refer to the format of the XML that the envelope uses. SOAP is a mature standard and is heavily used in many systems, but it does not use many of the functionality build in HTTP. While some consider it slow, it provides a heavy set of functionality which is a necessity in many cases. It might not be the best solution for browser-based clients, due to its custom format.
What is REST ?
The Representational State Transfer (REST) is another architectural pattern (resource-oriented), analternative to SOAP. Unlike SOAP, RESTful applications use the HTTP build-in headers (with a variety of media-types) to carry meta information and use the GET, POST, PUT and DELETE verbs to perform CRUD operations. REST is resource-oriented and uses clean URLs (or RESTful URLs). For example : http://www.developingthefuture.com/index.php?page=foo becomes http://www.developingthefuture.com/foo Note: Having query parameters doesnt exclude REST, the query parameters can actually complement the restful URL by making it more versatile (thanks Ugarit Ebla for pointing that in the comments ;] ) This kind of URLs syntax greatly improves both visibility and usability. It doesnt use any query strings, and it also provides certain SEO benefits (the crawlers just love plain text). The body of the REST message can be XML, JSON or any other format, although JSON is usually the preferred choice. On the other hand, you cant use JSON with SOAP. Or at least not entirely, because SOAP uses XML by definition for its envelope. It should also mentioned that REST is, by design, protocol-agnostic, although it is usually used with HTTP. Read more: Whats the difference between JSON and XML ?
Summary
SOAP A service architecture XML based Runs on HTTP but envelopes the message Slower than REST Very mature, a lot of functionality Not suitable for browser-based clients
REST A service architecture (resource-oriented) Uses the HTTP headers to hold meta information (although it is protocol-agnostic) Can be used with XML, JSON or whatever necessary Usually used with JSON due to the easily parsable content Faster than SOAP It uses semantic media types
OData A protocol Based on HTTP, AtomPub and JSON RESTful by design Microsoft implementation, yet truly open source Used in the latest Microsoft service-oriented technologies (more on that later)
My idea of writing this article was to introduce you to the new Asp.Net Web API, compared to the various services in WCF (SOAP services, WebHttpServices, Data services, etc.) and to the Asp.Net MVC alternative. I decided, however, to first give you this quick introduction so you can know whats behind the new Microsoft service-oriented technologies (although these terms are platform-agnostic) and why it was used. In my next article on the subject, Ill focus on the practical part and the actual technologies/frameworks that use these protocols and patterns. If you want to read more on the topic, you can check the following document written by Vivin Suresh Paliath, which forms a nice introduction into the differences between SOA, ROA, SOAP and REST in general.
End MISC.
foundational knowledge and skills to rapidly get up and running building PowerBuilder RESTful Web Service clients. Along the way I'll share with you a few tips and workarounds.
Introduction
PowerBuilder 12.0 .NET provided the ability to call SOAP-based web services using Microsoft's .NET 3.5 WCF API. I encourage those of you not familiar with WCF and SOAP to view my PowerBuilder WCF primer and StockTrader reference application overview hosted on Sybase.com. You can get to all my free tutorials fromhttp://yakovwerde.ulitzer.com/node/1551687. New with version 12.5, along with an upgrade to WCF 4.0, is the ability to call RESTful web services, an increasingly popular mechanism for accessing remote resources in SOA applications. In this article I'll help you gain some foundational understanding and definitions, then familiarize you with the mechanics of coding a client to retrieve data from a responseoriented RESTful service. In Part 2, I'll explore the three types of request-oriented operations.
One pragmatic difference between WSDL / SOAP services and RESTful services from the client viewpoint is the amount of onus placed on the client developer. SOAP services are fully described in a WSDL document, including their service methods, input parameters and return types. A PowerBuilder developer has no responsibility other than to input the WSDL location into the wizard or project painter and click the generate proxy button. The project painter does the rest. SOAP calls are also method based. At runtime the developer instantiates a single proxy and invokes specific methods as necessary. With RESTful services, however, the developer has more responsibility in defining the interface. He has to get hold of either a schema (XSD) document or .NET assembly that fully describes the types in the returned XML or JSON, OR a sample result set with sufficiently varied data to help the proxy generator decipher the return structure. He also has to know enough about the structure of the return type so as to be able to review the wizard's work and make corrections as necessary (more about this later). Calls to a RESTful service are not method based - simply navigating to the service URI with correct parameters appended gets you a response. This means there is one proxy per service (method), hence more code objects to maintain.
What Is JSON?
Depending on how they are implemented, RESTful web services can return data in one of several standard formats. Among the possible formats are XML, CSV, RSS, ATOM and JSON. PowerBuilder 12.5 allows you
to choose either XML or JSON for your transfer format. What is JSON? The upshot is that JSON is a JavaScript / AJAX browser friendly data transfer format. Because AJAX is a pervasive web technology, many services are only available in JSON flavor. Listing 2 provides some useful references from which you can get more background on JSON. JSON presents no problem for PowerBuilder! At design time you can provide a sample data set in JSON or XML format to the project painter. The project painter will parse the sample data, JSON data and generate the .NET reference objects you'll need to work with your data. At runtime JSON-based data transfer is parsed and converted to .NET value objects. The good news is that as a PB programmer you will not have to write JSON; however, you will have to read it to understand how a result set is constructed. 1. 2. Quick overview of this JSON JSON, a formal definition
Listing 2: Useful JSON References
Viewing JSON
IE 9 does not have a native facility for viewing JSON data. You'll need to use a tool to view the output data. One such tool is http://www.jsonviewer.com/. Once on the page, input the full invocation URL and click the Get JSON and Parse' button. Figure 1 shows what you might see.
If you are using Fiddler to monitor HTTP traffic (http://www.fiddler2.com/fiddler2), install the JSON viewer.Figure 2 shows how you can view returned JSON objects in Fiddler.
Getting Started
Here's a list of the information you'll need to have handy before entering inputs in the RESTful service project wizard: 1. 2. 3. 4. 5. The name of PBL into which you want to save your project object (usually the same pbl containing the project object you use to generate you EXE). The name of PBL into which the project painter will generate the code for your proxy class (you may want a separate pbl just for proxies that you can batch refresh if need be). The web method type GET, POST, PUT or DELETE. A name for your proxy class. You will interact with this class in your code. I'd suggest using the P_ prefix as part of your name. A name for the NameSpace you want to put your proxy class in - you can leave it blank to use the default namespace.
6. 7. 8.
9. o o o
The URI for the service including any parameters needed for the call. The service's return data format: XML or JSON. A name for a generated assembly. This assembly will contain value objects used as parameters and/or return types. It will be added by the wizard to your target as a reference. This name will also become the namespace for the assembly. A source to help the painter determine the return data type. There are three options, choose one: A schema document (XSD) that defines the structure of the returned dataset. A preexisting assembly that formally defines the return type structure A sample XML snippet or JSON object whose data is rich and robust enough that the tool can figure out the data types from its contents.
Sidebar Tip
As shown in Figure 4 you can cause the generator to include input parameters on the GetMessage( ) method by changing Service URL literal values to tokens. Identifiers inside { } will become parameter names. If you leave the literal values in, the generator will emit a parameter-less method call.
Sidebar Tip
The invocation method for a GET will always be named GetMessage( ). It is a good practice to include the service name as part of its corresponding proxy class name. This will make its intent clear.
Sidebar Tip
If you use a sample dataset (XML or JSON) to generate your reference assembly, it's important that you examine the emitted assembly to verify the data type of each property. Occasionally the Microsoft parser will misinterpret a property's type. You'll want to correct that before moving on. There is no intermediate source code for the reference assembly, so your only recourse is to supply values to the project object that will cause it to render the property correctly. For example, a supplied postalCode element with the value 07960' was generated as a UInt16 instead of the expected String type. Supplying the value x7960' forced the type to be rendered as a String.
Generated Artifacts
Let's take a more in-depth look at the generated code artifacts. Figure 13 shows the three kinds of objects generated from a project object.
Project Object is a place to input your choices and a front end onto Microsoft and PowerBuilder code generation tools. You click the Generate Proxy button on the Project Object's PainterBar to kick off the code generation process Proxy Class is the class you instantiate in your code and use to call the service. Don't modify the generated code. Any changes you make to this code object will be lost when you regenerate your proxy.
To extend or modify this code, inherit from this class and write your changes in the descendant. You instantiate a proxy type object and callGetMessage( ) passing appropriate parameters to invoke the service. Figure 14, shows the contents of a typical Proxy class fronting a call to a GET method.
Request and Response Assemblies contain value objects returned by a GET call or passed as parameters to DELETE, POST and PUT calls. The WCF infrastructure handles converting JSON & XML into value objects and vice versa. You are spared from dealing with low-level conversion issues. Usually there will be a wrapper object that may or may not have data properties. It's the equivalent of the root element in an XML document. The wrapper object will have an array of value objects. These are the repeating roworiented XML structures. The value object will have some set of return specific data values. Figure 15 shows the contents of a typical Response Assembly.
Note that even in well-designed applications, things can go wrong that are outside the client developer's control. For example, at runtime a service can be down or totally unavailable at the known URI. Therefor even though exception handling is optional, it's a best practice to avoid runtime system errors by scripting service calls inside TRY CATCH blocks that include a robust handler for problematic conditions.
Sidebar Tip
Using a single line DataWindow expression to directly load a data buffer from a PowerScipt NVO array works great. However, directly assigning a .NET value object array to a DataWindow buffer using an expression throws a runtime error. As a result you have to take a more time and labor code intensive approach. You must either (a) iterate the .NET object array and call SetItem( ) for each value OR (b) assign the .NET value array to an equivalent intermediate PowerScript NVO type array and then assign it to a DataWindow.
Sidebar Tip
Unfortunately, Web Service DataWindow Objects are only SOAP compatible. They have not yet become RESTful aware. To use a DataWindow for data display, you'll need to declare an external data source DataWindow and manually populate its buffer from the RESTful WS call return.
Conclusion
RESTful services are becoming pervasive on the Web. The APIs of many popular services, such as Google are Yahoo, are available as RESTful services. PowerBuilder 12.5 .NET programmers now have the ability to integrate calls to RESTful services in their applications using standard tools and technologies. Long Live PowerBuilder!
Introduction
As a teenager, one of my favorite TV shows was "The Wild Wild West." The show's description goes like this, "... a 60 minute western action series on CBS that was like no other. Special Agents James West and Artemus Gordon were spies for President Ulysses S. Grant shortly after the civil war. In every other way, they could be easily confused with James Bond of the 20th century. They had a "high-tech" (for its day) railroad car stocked with a compliment of advanced weapons. James West especially seemed to woo every beautiful woman he encountered. The agents' typical mission involved saving the United States from some disaster or from being taken over by some evil genius." Just in case you're curious or are a fan like me, here's a link to the first part of a full episode on YouTube. What do RESTful services have to do with the Wild Wild West? In my mind, lots. First, there's the "wildness" part. As even a brief comparison between service provider APIs will show you, all RESTful services are not created equal. Each service provider, while loosely conforming to the state representation paradigm, creates requests and responses in formats that suit their individual styles and predilections. The onus for implementing the client side of the service falls on the developer. Then there's the inventive side of things. Just like special agent Artemus Gordon, a RESTful client developer needs gadgets, inventiveness, and a continual awareness that she's dealing with an informal (enemy) specification. Plus, on the PowerBuilder side, there's no direct support for integrating with DataWindow technology (yet), so you'll have to invent ways to get data into and out of a display. There's also a need to protect your app against outside issues by wrapping calls in appropriate try catch blocks to handle possible HTTP exceptions in order to keep your app responsive and stable. In my opinion, without a formal schema and metadata description support, configuring RESTful state service clients will remain an art. I have to admit that I stumbled many times during experiments while writing this article. I tried calling services whose communication format didn't quite match the generally expected format. One service provider expected parameters to be passed and results returned in lineseparated text values in the message body instead of formatting data as XML or JSON. After quite a bit of poking and debugging it became apparent PowerBuilder will only generate and interpret message body content formatted as JSON and XML. There is no way to translate from any other format. All the low-level details are handled internally and there is no way to get inside the message to change the format. Another service provider showed their API in terms of JSON data sets, but after hours of experimentation and a little help from engineering, we discovered that the service needed multipart/form-data with the JSON sent as a form parameter. This is not a supported format. So e caveat emptor, make sure the service provider has a traditional' form of RESTful API. Luckily, I believe most of the big boys' with widely used APIs do.
Here are a series of tips that I discovered while building my application: Tip 1: The project object owns its generated proxy object. That means that any modifications you make to it will be lost if you regenerate the proxy. Because I needed to make modifications to the generated code, I adapted the strategy of using project object generation as a starting point only. Once the proxy objects were generated to my liking, I deleted the project object to avoid accidentally nuking my code. Tip 2: If you have several services that use an identical request object or return the same result structure, you can reuse your value object definitions. Generate once, use many. Just pick them on the wizard or in the project object. Tip 3: The only door into a new project object is in via the Wizard. This is unlike Classic where there were two doorways into a new project (Wizard or empty project painter page). Tip 4: Here are a couple of neat XML sample data parsing features: First, if an XML element in the sample dataset has attributes, the attribute values are returned as part of the generated value object. Figure 4
shows a sample response dataset containing attributes; Figure 5 show the corresponding generated value object. Second, as you can see from Figure 6 that nested XML structures becomes separate objects within the generated assembly.
With these project object details behind us we can now move on to two important runtime housekeeping needs: return status checking and exception handling.
PBWebHttp.WebMessage msg //generated code PBWebHttp.MessageStatus l_msg_status //my custom addition Try msg = m_service.GetMessage() //an exception was not thrown - check the status of the outcome l_msg_status= msg.Status
Exception Handling
Wizard-generated proxy code does not contain any exception handling logic. Any exceptions that occur are thrown up to the caller for processing. Unhandled, these exceptions become system errors. In the web world, Response status codes in the 400 range indicate client errors; those in the 500 range signal server errors. In WCF 400 and 500 codes raise exceptions. Best coding practices mandate robust exception handling. Depending on the level of detail you need to report on, you can handle exceptions either at the proxy method caller level or within the proxy method call itself. RESTful service methods, predicated on HTTP, usually throw a System.Net.WebException. Although the common System.Exception ancestor property Message contains a description of what went wrong, it's more useful to directly test the value of the returned status code. Luckily the WebException contains a reference to the returned Response object which holds the status code. Listing 2 shows an example of testing the status code when a call fails.
Collapse | Copy Code
if l_resp.StatusCode = System.Net.HttpStatusCode.Unauthorized! then //check its status code MessageBox('Your Credentials Are Invalid', 'Uid=' + uid + '~r~nPwd=' + pwd ) return Result end if
Listing 2: Testing the status code
Now that you are aware of housekeeping issues, let's take a look at security concerns.
Basic Authentication
WCF supports various forms of authentication ranging from None up to Digital Certificates. When using Basic Authentication you place your credentials in the user ID and password in request header fields. If HTTP is used, the credentials are encrypted within in a plain text header (however, freely available programs such as Fidder can decrypt SSL). If HTTPS is used, then SSL encryption is applied to all transferred packets. The client/server negotiation algorithm is: (1) Client makes a request; (2) Server responds with a 401 unauthorized response; (3) Client responds with a request including a login header containing a user id and password; (4) The client automatically includes the header in all requests for the duration of the exchange. Figure 8 show the conversation as revealed by Fiddler. For a more detailed discussion see http://www.4guysfromrolla.com/articles/031204-1.aspx
From the PB WCF perspective, your programming job is to set up the credentials for the exchange. The low-level runtime exchange process is handled internally by the infrastructure. A minor challenge is that from the PowerBuilder coding perspective you're navigating into partially uncharted waters. There is no PowerBuilder documentation on the members of the Sybase.PowerBuilder.WCF.Runtime assembly. However, armed with a basic understanding of WCF and a few minutes to examine the members of the referenced assembly I imagine that you will be able to figure out what to do. Here's the basic algorithm: 1. In the constructor of your proxy class, instantiate a WebClientCredential object and set your credentials and authentication type into it. Figure 9 shows the WebClientCredential class and its members (it's just a value object). a. Set a value for the AuthenticationMode using a value from the AuthenticationMode enumeration. In our case we set the value to Basic! b. Provide your user ID and password. Assign your WebClientCredential object to your WebConnection object. The WebConnection is already instantiated and has the identifier name restConnectionObject. Figure 9 shows this object with the important property. Call your service as usual. Be sure to include exception handling code that tests for the 401 HTTP error.
2.
3.
// vvvvv----Project Generated Code----vvvv m_service = create PBWebHttp.RestService("http://phprestsql.sourceforge.net/tutorial/user?firstname={p_first}&sur name={p_last}&email={p_email}&company_uid={p_id}", PBWebHttp.WebMessageFormat.Xml!, PBWebHttp.WebMessageFormat.Xml!) restConnectionObject = create PBWebHttp.WebConnection restConnectionObject.Endpoint = http://phprestsql.sourceforge.net/tutorial/user?firstname={p_first}&surname={p_last}&email={p_ email}&company_uid={p_id} restConnectionObject.RequestMessageFormat = PBWebHttp.WebMessageFormat.Xml! restConnectionObject.ResponseMessageFormat = PBWebHttp.WebMessageFormat.Xml! // vvvvv----Custom Authentication Code----vvvv PBWebHttp.WebClientCredential lsCredential //configure credentials lsCredential = create PBWebHttp.WebClientCredential lsCredential.AccessAuthentication = PBWebHttp.AuthenticationMode.Basic! lsCredential.Password='demo' lsCredential.Username='p126371rw' restConnectionObject.ClientCredential = lsCredential //add credentials to connection
Listing 3
Conclusion
In addition to calling service methods, the PowerBuilder client-side developer is responsible for configuring authentication and authorization properties prior to making service calls as well writing code to handle server-side errors responses. With a bit of forethought this code can be written in a reusable manner to work in conjunction with project painter-generated proxy classes. With the addition of RESTful web service client-side infrastructure, PowerBuilder .NET clients can now enjoy the same service-oriented interoperability as other .NET languages. Long Live PowerBuilder!
MISC
. What is REST?
REST stands for Representational State Transfer. (It is sometimes spelled "ReST".) It relies on a stateless, client-server, cacheable communications protocol -- and in virtually all cases, the HTTP protocol is used. REST is an architecture style for designing networked applications. The idea is that, rather than using complex mechanisms such as CORBA, RPC or SOAP to connect between machines, simple HTTP is used to make calls between machines. In many ways, the World Wide Web itself, based on HTTP, can be viewed as a REST-based architecture.
RESTful applications use HTTP requests to post data (create and/or update), read data (e.g., make queries), and delete data. Thus, REST uses HTTP for all four CRUD (Create/Read/Update/Delete) operations. REST is a lightweight alternative to mechanisms like RPC (Remote Procedure Calls) and Web Services (SOAP, WSDL, et al.). Later, we will see how much more simple REST is. Despite being simple, REST is fully-featured; there's basically nothing you can do in Web Services that can't be done with a RESTful architecture.
REST is not a "standard". There will never be a W3C recommendataion for REST, for example. And while there are REST programming frameworks, working with REST is so simple that you can often "roll your own" with standard library features in languages like Perl, Java, or C#.
BY DR. M. ELKSTEIN 45 COMMENTS
Like Web Services, REST offers no built-in security features, encryption, session management, QoS guarantees, etc. But also as with Web Services, these can be added by building on top of HTTP: For security, username/password tokens are often used. For encryption, REST can be used on top of HTTPS (secure sockets).
... etc.
One thing that is not part of a good REST design is cookies: The "ST" in "REST" stands for "State Transfer", and indeed, in a good REST design operations are self-contained, and each request carries with it (transfers) all the information (state) that the server needs in order to complete it.
BY DR. M. ELKSTEIN 9 COMMENTS
Note how the URL's "method" part is not called "GetUserDetails", but simply "UserDetails". It is a common convention in REST design to use nouns rather than verbs to denote simpleresources.
The letter analogy A nice analogy for REST vs. SOAP is mailing a letter: with SOAP, you're using an envelope; with REST, it's a postcard. Postcards are easier to handle (by the receiver), waste less paper (i.e., consume less bandwidth), and have a short content. (Of course, REST requests aren't really limited in length, esp. if they use POST rather than GET.) But don't carry the analogy too far: unlike letters-vs.-postcards, REST is every bit as secure as SOAP. In particular, REST can be carried over secure sockets (using the HTTPS protocol), and content can be encrypted using any mechanism you see fit. Without encryption, REST and SOAP are both insecure; with proper encryption in place, both are equally secure.
BY DR. M. ELKSTEIN 16 COMMENTS
While REST services might use XML in their responses (as one way of organizing structured data), REST requests rarely use XML. As shown above, in most cases, request parameters are simple, and there is no need for the overhead of XML. One advantage of using XML is type safety. However, in a stateless system like REST, you should always verify the validity of your input, XML or otherwise! ****************** END MISC