Within the BackgroundAgents solution in the
downloadable sample code is a project named
WPUnleashed.BackgroundAgents.Web. This project exposes a WCF service
named BackupService, which allows the phone app to save files to the
Backups directory on the server by way of its SaveFile
method (see Listing 1). The SaveFile
method accepts a Stream, which is written to a file on the server. The
unique ID of the user is also sent to the server to allow correct
retrieval of the file at a later time.
LISTING 1. BackupService
Class
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
[AspNetCompatibilityRequirements(
RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class BackupService : IBackupService
{
public void SaveFile(string userId, string fileName, Stream fileStream)
{
string location = string.Format(
@"~\Backups\{0}_{1}", userId, fileName);
var filepath = HttpContext.Current.Server.MapPath(location);
using (Stream outputStream = File.OpenWrite(filepath))
{
CopyStream(fileStream, outputStream);
}
}
static void CopyStream(Stream input, Stream output)
{
var buffer = new byte[8 * 1024];
int streamLength;
while ((streamLength = input.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, streamLength);
}
}
}
There is no retrieval method in the WCF service because an ordinary HTTP GET request is used to download the file.
The WPUnleashed.BackgroundAgents contains a
web reference to the WPUnleashed.BackgroundAgents.Web project, and the
service is consumed within the TodoListViewModel
class.
1. Using URL Rerouting with a WCF Service
The Web Application project uses URL rerouting to allow the BackgroundTransferRequest
to pass the user ID and filename to the service via the URL.
The routing system on the server is initialized in the RegisterRoutes
method of the Global
class in the Web Application project. The URL routing APIs reside in the System.Web.Routing namespace. A new ServiceRoute
is added to the RouteTable
, so that when a request for the URL BackupService
arrives, the built-in WebServiceHostFactory
creates an instance of the BackupService
class to service the request. See the following excerpt:
public class Global : System.Web.HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
RegisterRoutes();
}
void RegisterRoutes()
{
RouteTable.Routes.Add(new ServiceRoute(
"BackupService", new WebServiceHostFactory(),
typeof(BackupService)));
}
...
}
The service interface for the backup service defines a UriTemplate
that maps the incoming request URL, which includes the user ID and filename, to the SaveFile
method parameters. This means that we are able to translate the
incoming URL and forward the call to the service method. See the
following:
[ServiceContract(Namespace = "http://danielvaughan.org")]
public interface IBackupService
{
[OperationContract, WebInvoke(
Method = "POST", UriTemplate = "UploadFile/{userId}/{fileName}")]
void SaveFile(string userId, string fileName, Stream fileStream);
}
URL rerouting is an elegant way of
providing a WCF service with extra information, such as the user’s ID,
while still remaining compatible with the BackgroundTransferRequest
and its simple Uri UploadLocation
property.