-
Notifications
You must be signed in to change notification settings - Fork 4
Services
The high level service operation API uses LINQ expressions to provide a fluent interface for building service operation requests. It makes calling remote services almost as easy as calling local methods.
Note: LINQ expressions were introduced in .NET 3.5 so the .NET 2.0 version of this library doesn't support the service operation API.
The CallService
method takes a lambda expression containing a single method call and uses it to build a service request payload and a target URL path. The method name should match the service name or have an alternate name specified via the SDataServiceOperation
attribute. Similarly, the parameter names should match the request property names or specify alternatives via the SDataServiceParameter
attribute. There's no need to actually implement the method since it's only used as a convenient way to define the service interface and is never actually executed.
Static service operations don't require entity context. The following example calls the static GetUserContext
service and outputs the three user values returned.
var client = new SDataClient("http://example.com/sdata/slx/system/-/")
{
UserName = "admin",
Password = "password"
};
var user = await client.CallServiceAsync(() => Global.GetCurrentUser());
Console.WriteLine(user.UserId);
Console.WriteLine(user.UserName);
Console.WriteLine(user.PrettyName);
public static class Global
{
public static CurrentUser GetCurrentUser()
{
throw new NotSupportedException();
}
}
public class CurrentUser
{
[DataMember(Name = "userId")]
public string UserId { get; set; }
[DataMember(Name = "userName")]
public string UserName { get; set; }
[DataMember(Name = "prettyName")]
public string PrettyName { get; set; }
}
Instance service operations act on a specific entity instance and therefore require entity context. This can be passed in the URL via a selector or in the posted payload as a key or a full resource. The following example reads an activity then completes it.
var activity = await client.GetAsync<Activity>("VDEMOA000001");
var history = await client.CallServiceAsync(
() => activity.Complete("UDEMOA000001", "Complete", DateTime.Now));
Console.WriteLine(history.Id);
Console.WriteLine(history.UserId);
Console.WriteLine(history.Result);
Console.WriteLine(history.CompletedDate);
[SDataPath("activities")]
public class Activity
{
[SDataProtocolProperty(SDataProtocolProperty.Key)]
public string Id { get; set; }
[SDataServiceOperation(InstancePropertyName = "entity",
PassInstanceBy = InstancePassingConvention.ObjectProperty,
ResultPropertyName = "Result")]
public History Complete(string userId, string result, DateTime completeDate)
{
throw new NotSupportedException();
}
}
public class History
{
[SDataProtocolProperty(SDataProtocolProperty.Key)]
public string Id { get; set; }
public string UserId { get; set; }
public string Result { get; set; }
public DateTime? CompletedDate { get; set; }
}
The SDataServiceOperation
attribute defines important metadata that's used to build the request payload and interpret the response payload. The InstancePropertyName
property specifies the name of the instance context property on the request and the ResultPropertyName
property specifies the name of the response property that should be deserialized as the method's return value.
Services can also be called without POCOs and stub methods using the more basic Post
method. Both the request payload and the target URL path must be built manually when using this approach. The following example completes an activity using an anonymously typed request payload and outputs the ID of the created history record.
var service = new
{
Request = new
{
entity = "VDEMOA000001",
userId = "UDEMOA000001",
result = "Complete",
completeDate = DateTime.Now
},
Response = new
{
HistoryId = default(string)
}
};
service = await client.PostAsync(service, "activities/$service/Complete");
Console.WriteLine(service.Response.HistoryId);
It's important that the anonymous type include a response property with property stubs so that the desired response data is captured during deserialization.
More information on service operations can be found in section 11 of the SData specification.