Marcos Vainer Loeff

Developing custom interfaces to fetch data from external RESTful service to the PI System

Blog Post created by Marcos Vainer Loeff Employee on Nov 4, 2013

Introduction

 

 

Representational State Transfer (REST) has gained widespread acceptance across the Web as a simpler alternative to SOAP and WSDL(Web Services Description Language). A key evidence of this shift in interface design is the adoption of REST by mainstream Web 2.0 service providers—including Yahoo, Google, and Facebook—who have deprecated or passed on SOAP and WSDL-based interfaces in favor of an easier-to-use, resource-oriented model to expose their services.

 

OSIsoft is also following the same path. If you come to our vCampus Live! 2013, you will have the opportunity to be ahead of the curve and be among the first to work with in-progress unreleased versions of the new RESTful API’s web services on top of the PI System.

 

Nevertheless, this blog post is about how to fetch data into your PI System from external servers through RESTful Web services.

REST

In REST architecture there is always a client and a server where the communication is always initiated by the client. The client and server are decoupled by a uniform interface there by making both the client and server to develop independently. Every resource in the server is accessed by a unique address (URI). When the client access a resource the server returns a representation of the resource based upon the request header. The representations are usually called as media-types or MIME types.

 

0525.Rest_5F00_arch.png

REST vs. SOAP

Multiple factors need to be considered when choosing a particular type of Web service, that is between REST and SOAP. The table below breaks down the features of each Web service based on personal experience.

 

REST

  • The RESTful Web services are completely stateless. This can be tested by restarting the server and checking if the interactions are able to survive.
  • Restful services provide a good caching infrastructure over HTTP GET method (for most servers). This can improve the performance, if the data the Web service returns is not altered frequently and not dynamic in nature.
  • The service producer and service consumer need to have a common understanding of the context as well as the content being passed along as there is no standard set of rules to describe the REST Web services interface.
  • REST is particularly useful for restricted-profile devices such as mobile and PDAs for which the overhead of additional parameters like headers and other SOAP elements are less.
  • REST services are easy to integrate with the existing websites and are exposed with XML so the HTML pages can consume the same with ease. There is hardly any need to refactor the existing website architecture. This makes developers more productive and comfortable as they will not have to rewrite everything from scratch and just need to add on the existing functionality.
  • REST-based implementation is simple compared to SOAP.

 

 

SOAP (as PI Web Services)

  • The Web Services Description Language (WSDL) contains and describes the common set of rules to define the messages, bindings, operations and location of the Web service. WSDL is a sort of formal contract to define the interface that the Web service offers.
  • SOAP requires less plumbing code than REST services design, (i.e., transactions, security, coordination, addressing, trust, etc.) Most real-world applications are not simple and support complex operations, which require conversational state and contextual information to be maintained. With the SOAP approach, developers need not worry about writing this plumbing code into the application layer themselves.
  • SOAP Web services (such as JAX-WS) are useful in handling asynchronous processing and invocation.
  • SOAP supports several protocols and technologies, including WSDL, XSDs, SOAP, WS-Addressing

In a nutshell, when you're publishing a complex application program interface (API) to the outside world, SOAP will be more useful. But when something with a lower learning curve, and with lightweight and faster results and simple transactions (i.e., CRUD operations) is needed, my vote goes to REST.

Using HTTP methods explicitly

One of the key characteristics of a RESTful Web service is the explicit use of HTTP methods in a way that follows the protocol as defined by RFC 2616. HTTP GET, for instance, is defined as a data-producing method that's intended to be used by a client application to retrieve a resource, to fetch data from a Web server, or to execute a query with the expectation that the Web server will look for and respond with a set of matching resources.

 

REST asks developers to use HTTP methods explicitly and in a way that's consistent with the protocol definition. This basic REST design principle establishes a one-to-one mapping between create, read, update, and delete (CRUD) operations and HTTP methods. According to this mapping:

  1. To create a resource on the server, use POST.
  2. To retrieve a resource, use GET.
  3. To change the state of a resource or to update it, use PUT.
  4. To remove or delete a resource, use DELETE.

 

 

The two common formats of the RESTful Web Services response are XML and JSON (JavaScript Object Notation). Below you can find an example of an XML and JSON response from a RESTful web service:

 

vCampus_Sessions.json

 
{
"Session" : [
{
"Title": "SharePoint® 2013 with PI WebParts 2013 and HTML5 Support",
"Presenters": ["Michael Wood","Bill Bernard"],
"Type": "Hands-On",
"Date": {"Day": "1","StartTime": "04:00 PM","EndTime": "05:00 PM","Duration": "01:00"},
"Description": "PI WebParts now supports WSP installation along with HTML5 support. In this lab you will install PI WebParts 2013 on SharePoint 2013. After a successful installation, you'll build SharePoint pages that show off the latest features of PI WebParts and access them with all the supported browsers.",
"Category": "PI Professional",
"Level": "200",
"Track": "1"
},
{
"Title": "Overview of the PI AF SDK",
"Presenters": ["Paul Kaiser"],
"Type": "Hands-On",
"Date": {"Day": "1","StartTime": "02:30 PM","EndTime": "03:45 PM","Duration": "01:15"},
"Description": "Since the introduction of Rich Data Access (RDA) in PI AF SDK 2012, you can now access both time-series data and asset metadata from the PI System using a single SDK. The PI AF SDK is where OSIsoft is placing the majority of its SDK development effort. Come to this hands-on lab to learn all about the PI AF SDK and what it can do for you and your applications.",
"Category": "Developer",
"Level": "300",
"Track": "1"
}
]
}

 

 

 

vCampus_Sessions.xml

 

 

 

 

 
<?xml version="1.0" encoding="utf-8" ?>
<vCampusLiveSessions>
<Session>
  <Title>SharePoint® 2013 with PI WebParts 2013 and HTML5 Support</Title>
  <Presenters>
                <Presenter>Michael Wood</Presenter>
                <Presenter>Bill Bernard</Presenter>
  </Presenters>
  <Type>Hands-On</Type>
  <Date>
                <Day>1</Day>
                <StartTime>04:00 PM</StartTime>
                <EndTime>05:00 PM</EndTime>
                <Duration>01:00</Duration>
  </Date>
  <Description>PI WebParts now supports WSP installation along with HTML5 support. In this lab you will install PI WebParts 2013 on SharePoint 2013. After a successful installation, you'll build SharePoint pages that show off the latest features of PI WebParts and access them with all the supported browsers.</Description>
  <Category>PI Professional</Category>
  <Level>200</Level>
  <Track>1</Track>
</Session>
<Session>
  <Title>Overview of the PI AF SDK</Title>
  <Presenters>
                <Presenter>Paul Kaiser</Presenter>
  </Presenters>
  <Type>Hands-On</Type>
  <Date>
                <Day>1</Day>
                <StartTime>02:30 PM</StartTime>
                <EndTime>03:45 PM</EndTime>
                <Duration>01:15</Duration>
  </Date>
  <Description>Since the introduction of Rich Data Access (RDA) in PI AF SDK 2012, you can now access both time-series data and asset metadata from the PI System using a single SDK. The PI AF SDK is where OSIsoft is placing the majority of its SDK development effort. Come to this hands-on lab to learn all about the PI AF SDK and what it can do for you and your applications.</Description>
  <Category>Developer</Category>
  <Level>300</Level>
  <Track>1</Track>
</Session>
</vCampusLiveSessions>

 

 

 Both examples will be used to convert to C# objects.

Interacting With REST Services

 

 

In order to interact with a service you’ll edit code that sends HTTP/S requests comprised of the following basic building blocks:

 

Root URL + Service Identifier + Service Specific Resource Information

 

In order to define these components let’s look at an example.  You’ll run across use of this example soon in order to read a values from the Search and PI System REST services.

 

 

 

4188.address.jpg

 

Root URL is deployment environment specific. 

 

Service Identifier – In the example above we see that the Search service API is specified as the Service Identifier.  This is a reference to the Rich Data Access REST service.  

 

Service Specific Resource Information – Developing a REST service comprises thinking in resources, HTTP idioms, and hypermedia controls.  What resources will your service expose, what are their behaviors, and what are the syntax and semantics associated with related interactions? For the suite of REST services we have implemented this level of detail is summarized in the API documentation referenced in the previous section. 

Interface

 

 

In order to develop an interface, there are some hurdles that we need to overcome, which are listed below:

  1. GET and POST method in HTTP in .NET
  2. How to convert an XML or JSON response in a C# object
  3. How to send the values from C# objects to the PI System.

The last item, many of you already know. We can use the method UpdateValue or UpdateValues from PI AF SDK in order to send data to the PI System.   I won’t show you an example as there are a lot of threads with lots of code snippets. Hence, let’s focus on the first two.

Using HTTP GET method in .NET

 

 

The .NET Framework uses specific classes to provide the three pieces of information required to access Internet resources through a request/response model: the Uri class, which contains the URI of the Internet resource you are seeking; the HttpWebRequest class, which contains a request for the resource; and the HttpWebResponse class, which provides a container for the incoming response.

 

Below you can find a simple code snippet about how to receive a response from Internet/intranet sites. I am assuming that the reader possesses basic knowledge of C# and Visual Studio.

 

 

 
        public string HTTPGETResponse(string url)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = "GET";
            request.ContentType = " application/xml; charset=utf-8";
            request.Timeout = 60000;
            request.Credentials = new NetworkCredential(UserName, PassWord);
            HttpWebResponse HttpWResp = (HttpWebResponse)request.GetResponse();
            Stream streamResponse = HttpWResp.GetResponseStream();

            // And read it out
            StreamReader reader = new StreamReader(streamResponse);
            string response = reader.ReadToEnd();
            reader.Close();
            reader.Dispose();
            return response;
        }

 

How to convert an XML or JSON response into a C# object

 

 

Let’s suppose you have used the function HTTPGETResponse and you have stored the GET response in a string variable. This response could be in JSON or XML format. How can we convert the response into a C# object?

 

The answer is you will need to deserialize the response even if it is in the XML or JSON format. There are two examples below for each format. In these examples, the responses will be read from files and not from an HTTP response.

 

JSON

 

In order to deserialize a JSON response, you should use the Deserialize method from class JavaScriptSerializer of the System.Web.Script.Serialization namespace.  Please consider the example below to deserialize the file vCampus_Sessions.json.

 

Program.cs

 

 

 
using System.Web.Script.Serialization;
using System.IO;

namespace JSON_Example
{
    class Program
    {
        static void Main(string[] args)
        {    

            System.IO.StreamReader myFile = new System.IO.StreamReader(@"c:\vCampus_Sessions.json");
            string response = myFile.ReadToEnd();
            myFile.Close();
            Console.WriteLine(response);
            VCLSessions VCL13Session = (VCLSessions)new JavaScriptSerializer().Deserialize(response, typeof(VCLSessions));
            Console.ReadKey();
        }
    }
}


 

VCLSessionsJSON.cs

 


 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace JSON_Example
{
    public class VCLSessions
    {
        public List<Session> Session { get; set; }
    }

    public class Session
    {
        public string Title { get; set; }
        public List<string> Presenters { get; set; }
        public string Type { get; set; }
        public DateClass Date { get; set; }
        public string Description { get; set; }
        public string Category { get; set; }
        public int Level { get; set; }
        public int Track { get; set; }
    }

    public class DateClass
    {
        public int Day { get; set; }
        public string StartTime { get; set; }
        public string EndTime { get; set; }
        public string Duration { get; set; }
    }
}

 

 

In order to deserialize a response, you need to create a class with a compatible structure of the response, otherwise the method will throw an exception. If you want to learn more about how to create this class, please take a look here.

 

Instead of using the method above to deserialize the response, there is another possibility to do so by using JSON.NET. You can add this reference in your project by typing “Install-Package Newtonsoft.Json” on the Packager Manager Console.

 

If you want more examples about this topic, you might want to read  this article.

 

 

 

XML

 

For the XML format, the same concept is applied but Deserialize http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer.deserialize(v=vs.110).aspx method is used from XmlSerializer class. Please view the example below:

 

Program.cs

 

 

 
using System.Xml;
using System.Xml.Serialization;

namespace XML_Example
{
    class Program
    {
        static void Main(string[] args)
        {
            System.IO.StreamReader myFile = new System.IO.StreamReader(@"C:\vCampus_Sessions.xml");
            string objectData = myFile.ReadToEnd();
            myFile.Close();
            TextReader stream = new StringReader(objectData);
            var serializer = new XmlSerializer(typeof(VCLSessions));
            VCLSessions myVCLSessions = serializer.Deserialize(stream) as VCLSessions;    Console.ReadKey();
        }
    }
}

 

 

 

 

 

VCLSessionsXML.cs

 

 

 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Serialization;

namespace XML_Example
{
    [XmlRoot("vCampusLiveSessions")]
    public class VCLSessions
    {
        [XmlElement("Session")]
        public List<Session> Session { get; set; }
    }
   
    public class Session
    {
        public string Title { get; set; }
        [XmlArray("Presenters"), XmlArrayItem("Presenter")]
        public List<string> Presenters { get; set; }
        public string Type { get; set; }
        [XmlElement("Date")]
        public DateClass Date { get; set; }
        public string Description { get; set; }
        public string Category { get; set; }
        public int Level { get; set; }
        public int Track { get; set; }

    }

    public class DateClass
    {
        public int Day { get; set; }
        public string StartTime { get; set; }
        public string EndTime { get; set; }
        public string Duration { get; set; }

    }

}

 

 

 The XML example is very similar to JSON’s but the way the class was developed is slightly different as some attributes were added as  [XmlElement("Date")],[XmlArray("Presenters"), XmlArrayItem("Presenter")] or [XmlRoot("vCampusLiveSessions")].

 

Please refer to this article called “Using the XmlSerializer Attributes” to learn more about how you can create a class to deserialize XML response.

Conclusion

 

 

The objective of this blog post was to give you an introduction about what RESTful services are and how you can use them in .NET environment. Once the data objects created through the RESTful services are available, it is easy to send data to your PI System through PI AF SDK. Some REST API’s websites make the classes available for you, so that you can avoid having to write one to be used to convert to a C# object.

 

Stay tuned because my next blog post will be about the PI Web API (a RESTful service on top of the PI System) and if you are participating on the Programming Hackathon, I am sure you will be willing to read it.

 

 

 

 

Outcomes