Service operations are one of the important and powerful
mechanisms of ADO.NET Data Services extension. Service operations are necessary
when standard functionality of ADO.NET Data Services queries aren't enough. For
example, it is impossible to perform a complex query to a database, using the
light URI syntax ADO.NET Data Services. In this case it is possible to use
service operations. Also service operations can be used to generate content in
non-standard formats if it is necessary. For example, you can generate a
HTML-code with description of a web service. Also usage of service operations
makes it possible to provide access to any binary contents, for example, to
images.
Implementation of difficult queries to a data model is one
of most well-spread reasons to use service operations. You can build a big
request, with multiple join operations, additional conditions and sorting. To
implement such service operation you need to define a new method in a service.
Such method should have two specific features - return IQueryable collection as
a result and be marked with WebGet attribute.
Listing 4 - The definition of service operation
[WebGet]
public IQueryable<Customers> <span style='background:white'>GetCustomersWithOrders</span>()
{
return CurrentDataSource.Customers.Where(c => c.Orders.Count > 0);
}
In service operations it is possible to construct query of any
complexity and to return its to client. For the access to service operation it
is necessary to use the kind of address
"http://localhost:9580/WebDataService1.svc/GetCustomersWithOrders".
Also this operation will appear in service metadata. It can be checked up,
having accessed to the address
"http://localhost:9580/WebDataService1.svc/$metadata".
You can also use operations with parameters. It is useful
when the same query is executed several times and there is a changeable
parameter. To define this behavior you should specify a parameter in the
method. For example, it is possible to change the previous example and specify
quantity of orders.
Listing 5 - The definition of service operation
with parameter
[WebGet]
public IQueryable<Customers> GetCustomersWithCountOrders(int count)
{
return CurrentDataSource.Customers.Where(c => c.Orders.Count > count);
}
In this case for the access to operation it is necessary to
use the kind of address "http://localhost:9580/WebDataService1.svc/GetCustomersWithCountOrders?count=5".
Names of methods shouldn't be equal to collection names. As
a method returns result in a form of Iqueryable so it is possible to use all
opportunities of ADO.NET Data Services platform. For example, it is possible to
organize paging of results of operation execution. Also you can do filtration
and sorting.
WebGet method, that marks methods, means there is
opportunity to advert to service operations via GET HTTP-verb. Also it is
possible to provide other methods of treatment. For these purposes you should
use WebInvoke attribute instead of WebGet. Specifying a value of WebInvoke
attribute there is need to specify an HTTP-method to be used.
Listing 6 - The usage WebInvoke attribute
[WebInvoke(Method = "POST")]
public void SetCustomer()
{
// ...
}
Other HTTP-methods can be used in the same way.
Except receiving collections, service operations can be used
to get some individual results. For example, a service operation can help to
receive a data model image. For this purpose you need to create a method which
returns Stream object. This method should be marked with attributes WebGet and
SingleResult. SingleResult attribute indicates that the method returns not a
set of data but an individual result. Besides that, it is necessary to mark
with MimeType attribute to set value of "Content-Type" HTTP-header in
an HTTP-response. MimeType attribute is specified for each method separately.
It accepts two parameters - a name of a method and value of HTTP-header.
Listing 7 - The usage attributes both MimeType and
SingleResult
[MimeType("GetCustomerPhoto", "image/jpg")]
public class WebDataService1 : DataService<NorthwindEntities>
{
[WebGet]
[SingleResult]
public System.IO.Stream GetCustomerPhoto(string customerId)
{
//..
}
Similarly, you can generate and send a client HTML-content
or any other data. It is important to notice, that when you access to such
service operations, ADO.NET Data Services packs these data into XML format. To
avoid this effect and obtain these data without distortions it is necessary to
add a keyword "$value" in an address. For example, the address to
service access can look like
"http://localhost:9580/WebDataService1.svc/GetPhoto/$value".
Service operations, as well as containers, are also amenable
to rules of safety. For this reason, we should explicitly authorize the use of
service operations in InitializeService method. In IDataServiceConfiguration
interface there is SetServiceOperationAccessRule method that helps to do it. To
grant permission to all operations you can employ the following code.
Listing 8 - The definition of security rules
public class WebDataService1 : DataService<NorthwindEntities>
{
public static void InitializeService(IDataServiceConfiguration config)
{
// ...
config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
}
So, thanks to employing service operations it is possible to
expand functionality of web services based on ADO.NET Data Services platform
essentially.