Technically, web services are
part of the web role, but their use and development are so distinctly
different than web forms that we'll look at these separately. The web
services themselves can be written in any language supported by Azure,
but utilizing the Windows Communication Foundation (WCF) libraries in
.NET greatly simplifies the development of web services. The simple
storage services have their own REST API and client library developed,
but if we want to add data into SQL Azure, we'll have to create our own
web services.
Web services and WCF
A web service is not one single entity and consists of three distinct parts:
An endpoint, which is the URL (and related information) where client applications will find our service
A host environment, which in our case will be Azure
A service class, which is the code that implements the methods called by the client application
A web service endpoint is more than just a URL. An endpoint also includes:
The bindings, or communication and security protocols
The
contract (or promise) that certain methods exist, how these methods
should be called, and what the data will look like when returned
A simple way to remember the components of an endpoint is A/B/C, that is, address/bindings/contract.
Web services can fill many
roles in our Azure applications from serving as a simple way to place
messages into a queue, to being a complete replacement for a data access
layer in a web application (also known as a Service Oriented
Architecture or SOA). In Azure, web services serve as HTTP/HTTPS
endpoints, which can be accessed by any application that supports REST,
regardless of language or operating system.
The intrinsic web services libraries in .NET are called Windows Communication Foundation (WCF). As WCF is designed specifically for programming web services, it's referred to as a service-oriented programming model.
We are not limited to using WCF libraries in Azure development, but we
expect it to be a popular choice for constructing web services being
part of the .NET framework.
When
adding WCF services to an Azure web role, we can either create a
separate web role instance, or add the web services to an existing web
role. Using separate instances allows us to scale the web services
independently of the web forms, but multiple instances increase our
operating costs. Separate instances also allow us to use different
technologies for each Azure instance; for example, the web form may be
written in PHP and hosted on Apache, while the web services may be
written in Java and hosted using Tomcat. Using the same instance helps
keep our costs much lower, but in that case we have to scale both the
web forms and the web services together. Depending on our application's
architecture, this may not be desirable.
Securing WCF
Stored data are only as
secure as the application used for accessing it. The Internet is
stateless, and REST has no sense of security, so security information
must be passed as part of the data in each request. If the credentials
are not encrypted, then all requests should be forced to use HTTPS. If
we control the consuming client applications, we can also control the
encryption of the user credentials. Otherwise, our only choice may be to
use clear text credentials via HTTPS.
For an application with a wide
or uncontrolled distribution (like most commercial applications want to
be), or if we are to support a number of home-brewed applications, the
authorization information must be unique to the user. Part of the
behind-the-services code should check to see if the user making the
request can be authenticated, and if the user is authorized to perform
the action. This adds additional coding overhead, but it's easier to
plan for this up front.
There
are a number of ways to secure web services from using HTTPS and
passing credentials with each request, to using authentication tokens in
each request. As it happens, using authentication tokens is part of the
AppFabric Access Control, and we'll look more into the security for WCF
when we dive deeper into Access Control.
Jupiter Motors web service
In our
corporate portal for Jupiter Motors, we included a design for a client
application, which our delivery personnel will use to update the status
of an order and to decide which customers will accept delivery of their
vehicle. For accounting and insurance reasons, the order status needs to
be updated immediately after a customer accepts their vehicle. To do
so, the client application will call a web service to update the order
status as soon as the Accepted
button is clicked. Our WCF service is interconnected to other parts of
our Jupiter Motors application, so we won't see it completely in action
until it all comes together. In the meantime, it will seem like we're
developing blind.
Creating a new WCF service web role
When creating a web
service, we have a choice to add the web service to an existing web
role, or create a new web role. This helps us deploy and maintain our
website application separately from our web services. And in order for
us to scale the web role independently from the worker role, we'll
create our web service in a role separate from our web application.
Creating a new WCF service web role is very simple Visual Studio will do
the "hard work" for us and allow us to start coding our services.
First, open the JupiterMotors project. Create the new web role by right-clicking on the Roles folder in our project, choosing Add, and then select the New Web Role Project… option.
When we do this, we will be asked what type of web role we want to create. We will choose a WCF Service Web Role, call it JupiterMotorsWCFRole, and click on the Add
button. Because different services must have unique names in our
project, a good naming convention to use is the project name
concatenated with the type of role. This makes the different roles and
instances easily discernable, and complies with the unique naming
requirement.
This is where Visual Studio
does its magic. It creates the new role in the cloud project, creates a
new web role for our WCF web services, and creates some template code
for us. The template service created is called "Service1". You will see
both, a Service1.svc file as well as an IService1.vb file. Also, a web.config
file (as we would expect to see in any web role) is created in the web
role and is already wired up for our Service1 web service. All of the
generated code is very helpful if you are learning WCF web services.
This is what we should see once Visual Studio finishes creating the new project:
We are going to start afresh with our own services we can delete Service1.svc and IService1.vb. Also, in the web.config file, the following boilerplate code can be deleted (we'll add our own code as needed):
<system.serviceModel>
<services>
<service name="JupiterMotorsWCFRole.Service1" behaviorConfiguration="JupiterMotorsWCFRole. Service1Behavior">
<!-- Service Endpoints -->
<endpoint address="" binding="basicHttpBinding" contract="JupiterMotorsWCFRole.IService1">
<!--
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>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="JupiterMotorsWCFRole.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>
WCFnew Web Role, creating</system.serviceModel>
Let's now add a WCF service to the JupiterMotorsWCFRole project. To do so, right-click on the project, then Add, and select the New Item... option.
We now choose a WCF service and will name it as ERPService.svc:
Just like the generated code when we created the web role, ERPService.svc as well as IERPService.vb files were created for us, and these are now wired into the web.config file. There is some generated code in the ERPService.svc and IERPService.vb
files, but we will replace this with our code in the next section. When
we create a web service, the actual service class is created with the
name we specify. Additionally, an interface class is automatically
created. We can specify the name for the class; however, being an
interface class, it will always have its name beginning with letter I.
This is a special type of interface class, called a service contract.
The service contract provides a description of what methods and return
types are available in our web service.