Hi folks -
The purpose of this
post is to provide a simple basic understanding of what REST is, its rules, and
a simple example on how it differs from WCF, which has been the main service
layer in Dynamics AX 2012.
Moving on, in recent
years, it has become clear that HTTP is not just for serving up HTML/HTML5
pages. It is also a powerful platform for building Web APIs (D365 for Ops is a
good example) using a handful of verbs (GET, POST, and so forth) plus a few simple
concepts such as URIs and headers.
Additionally there
are six guiding constraints that define a RESTful system, these constraints
restrict the ways that the server may process and respond to client requests so
that, by operating within these constraints, the service gains desirable non-functional
properties, such as performance, scalability, simplicity, modifiability,
visibility, portability, and reliability. If a
service violates any of the required constraints, it cannot be considered
RESTful.
REST constraints
Client-server architecture
The first
constraints added to the hybrid style are those of the client-server
architectural style. The principle behind the client-server constraints is the
separation of concerns. Separating the user interface concerns from the data
storage concerns improves the portability of the user interface across multiple
platforms. It also improves scalability by simplifying the server components.
Stateless protocol
The client–server
communication is constrained by no client context being stored on the server
between requests. Each request from any client contains all the information
necessary to service the request, and session state is held in the client. The
session state can be transferred by the server to another service such as a
database to maintain a persistent state for a period and allow authentication.
The client begins sending requests when it is ready to make the transition to a
new state. While one or more requests are outstanding, the client is considered
to be in transition. The representation of each application state contains
links that may be used the next time the client chooses to initiate a new
state-transition.
Cacheability
Clients and
intermediaries can cache responses. Responses must therefore, implicitly or
explicitly, define themselves as cacheable or not to prevent clients from
reusing stale or inappropriate data in response to further requests.
Well-managed caching partially or completely eliminates some client–server
interactions, further improving scalability and performance.
Layered system
A client cannot
ordinarily tell whether it is connected directly to the end server, or to an
intermediary along the way. Intermediary servers may improve system scalability
by enabling load balancing and by providing shared caches. They may also
enforce security policies.
Code on demand
Servers can
temporarily extend or customize the functionality of a client by transferring
executable code. Examples of this may include compiled components such as client-side scripts such as JavaScript.
Uniform interface
The uniform
interface constraint is fundamental to the design of any REST service. It
simplifies and decouples the architecture, which enables each part to evolve
independently. The four constraints for this uniform interface are:
Resource identification in requests
Individual resources
are identified in requests, for example using URIs in Web-based REST systems.
The resources themselves are conceptually separate from the representations
that are returned to the client. For example, the server may send data from its
database as HTML, XML or JSON, none of which are the server's internal
representation. A good example of this can be seeing in power apps when
creating JSON mappings.
The above is
important to understand as when creating RESTful services to interact with our
power apps or flow, these constraints will help us to create a true MVC pattern
(using MS tools) so we can take advantage of scalability, reusability, and
smart data management. Let's look at a simple comparison between WCF and
REST.
Services - WCF/REST
Unlike WCF where a
service is an address to a physical file (i.e. an address that maps directly to
a service class or .svc file), Service addresses
with MVC are REST-style routes
that map to controller methods - they fit nicely with REST-API Specs.
Let's look at an
example of a Task Management routine with WCF:
[Service Contract]
public interface
ITaskService
{
[Operation
Contract]
Task
GetTask(long Task ID);
}
public class
TaskService : ITaskService
{
private
readolny IRepository _repository;
Public
TaskService(IRepository repository)
{
_repository
= repository;
}
Public
Task GetTask(long taskId)
{
Return
_repository.Get<Task>(taskId);
}
}
The below code
achieves the same result than the above one. The only difference is that is
built with MVC4 and it also is JavaScript friendly (JavaScript meaning for any
web based app). The main difference is that the below code would involve creating a controller instead of a service class.
Further, the method that takes care of retrieving the TaskId exist in the
controller itself, unlike WCF where it would be defined by a contract.
Public class
TaskController : Controller
{
private
readolny IRepository _repository;
Public
TaskController(IRepository repository)
{
_repository
= repository;
}
Public
ActionResult Get(long taskId)
{
Return
JSON(_repository.Get<Task>(taskId));
}
}
In order to retrieve
a single task - the MVC4 will not need SOAP, or any service class to contract
with along with an operation. The call will look like this (assuming there is
an appropriately configured route.
Let's move further,
and look an example with the ApiController.
The URL will look different as the above example contains the Get in the URL. The ApiController base class
was built to enable RESTful services, and by using it we would only need to
return the object(s) in a collection and the data related to that collection.
Public class
TaskController : ApiController
{
private
readolny IRepository _repository;
Public
TaskController(IRepository repository)
{
_repository
= repository;
}
Public
Task Get(long taskId)
{
Return
repository.Get<Task>(taskId));
}
}
If we note, in the
address above we don't include the method name (i.e. Get) like we did in the
example where we were using the Controller base class instead of the
ApiController one. The amazing reason for this is because when using the
ApiController base class, it automatically maps to the corresponding controller
methods, therefore it helps us to create API the flows more naturally with the
REST architecture.
Thanks all for now!