Вот полное пошаговое руководство по созданию службы резервного копирования WCF для приложений Windows Phone.
Вы можете реализовать свой собственный хостинг с дешевым хостинг-сервером, таким как GoDaddy. Вы можете найти сделку на $ 5 / месяц. Лично я считаю более профессиональным сохранение данных вашего приложения на частном сервере или в облачном решении, а не ретрансляцию в SkyDrive.
Для этого необходимы две вещи:
A- Внедрение службы на вашем сервере.
B- Внедрение клиентского кода для отправки ваших данных.
Кроме того, вы можете скачать полное решение в конце статьи.
А) Сторона сервера
1- Давайте начнем с самой сложной части. После того, как вы найдете хост-сервер, который поддерживает платформу .NET 4.0, вы создаете приложение-службу WCF:
2- Переименуйте файл IService1.cs в IFileUploader.cs.
3- Замените содержимое файла IFileUploader.cs следующим:
using System.Runtime.Serialization;
using System.ServiceModel;
namespace FileUploadService
{
[ServiceContract]
public interface IFileUploader
{
// Returns null when there is no error, otherwise it is the exception message.
[OperationContract]
string Upload(UploadFile uploadFile);
}
[DataContract]
public class UploadFile
{
// Don't forget to set the variable FileUploadDirectoryWithReadWritePermission in your Web.config and set read/write permission in your web hosting.
// RelativeDirectory should be in the form as /Path1/Path2/ or null for the root directory.
[DataMember]
public string RelativeDirectory { get; set; }
[DataMember]
public string FileName { get; set; }
[DataMember]
public byte[] Content { get; set; }
}
}
Этот интерфейс содержит только метод Upload. Для загрузки требуется UploadFile, который содержит только 3 свойства: RelativeDirectory, FileName и Content.
4- Переименуйте файл Service1.svc в FileUploader.svc.
5- Заменить содержимое FileUploader.svc следующим:
using System;
using System.Configuration;
using System.IO;
using System.Web.Hosting;
namespace FileUploadService
{
public class FileUploader : IFileUploader
{
#region IFileUploader Members
public string Upload(UploadFile uploadFile)
{
string message = null;
try
{
string path = HostingEnvironment.MapPath(string.Format("~/{0}",ConfigurationManager.AppSettings["FileUploadDirectoryWithReadWritePermission"]));
if (path != null)
{
if (uploadFile.RelativeDirectory != null && uploadFile.RelativeDirectory.StartsWith("/"))
{
path = string.Concat(path, uploadFile.RelativeDirectory);
}
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
if (!string.IsNullOrEmpty(uploadFile.FileName))
{
using (FileStream fileStream = File.Open(Path.Combine(path, uploadFile.FileName), FileMode.Create))
{
using (var binaryWriter = new BinaryWriter(fileStream))
{
binaryWriter.Write(uploadFile.Content);
}
}
}
}
}
catch (Exception exception)
{
message = exception.Message;
}
return message;
}
#endregion
}
}
6- Замените содержимое файла Web.config на:
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="FileUploadDirectoryWithReadWritePermission" value="/backup/" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.0" />
<customErrors mode="Off" />
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="FileUploadBehavior">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="FileUploadBehavior" name="FileUploadService.FileUploader">
<endpoint address="" name="basicHttpStream" binding="basicHttpBinding"
bindingConfiguration="httpLargeMessageStream" contract="FileUploadService.IFileUploader" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<bindings>
<basicHttpBinding>
<binding receiveTimeout="00:10:00" sendTimeout="00:10:00" openTimeout="00:10:00" closeTimeout="00:10:00"
name="httpLargeMessageStream" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647">
<readerQuotas maxArrayLength="2147483647" maxStringContentLength="2147483647" />
</binding>
</basicHttpBinding>
</bindings>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
</system.webServer>
</configuration>
Этот файл имеет два важных раздела:
— Параметр FileUploadDirectoryWithReadWritePermission используется файлом FileUploader.svc и будет использоваться в вашей общей папке позже.
<appSettings>
<add key="FileUploadDirectoryWithReadWritePermission" value="/backup/" />
</appSettings>
— Раздел о длине параметров услуги: здесь не нужно все понимать. Это просто работает как есть. Если вам интересно, я предлагаю вам прочитать документацию по MSDN.
<bindings>
<basicHttpBinding>
<binding receiveTimeout="00:10:00" sendTimeout="00:10:00" openTimeout="00:10:00" closeTimeout="00:10:00"
name="httpLargeMessageStream" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647">
<readerQuotas maxArrayLength="2147483647" maxStringContentLength="2147483647" />
</binding>
</basicHttpBinding>
</bindings>
7- Сервис готов к публикации. Щелкните правой кнопкой мыши проект FileUploadService и выберите «Опубликовать». В зависимости от вашего веб-хостинга, вам нужно установить информацию.
Для GoDaddy:
— Используйте метод FTP.
— Установите целевое местоположение. Для меня я использовал ftp://ftp.ultimatepokermanager.com/upm/ServerTest
— установить учетные данные
8. Самая сложная задача — настроить параметры приложения для службы WCF в службе хостинга. В GoDaddy это в IIS Management в разделе Инструменты. Вам необходимо проверить анонимный доступ и установить корень приложения.
Тест upm \ servertest указывает на http://www.ultimatepokermanager.com/upm/servertest
8- Чтобы проверить, работает ли ваша служба, откройте браузер и введите адрес веб-службы. С моим веб-сервисом адрес:
http://www.ultimatepokermanager.com/upm/servertest/FileUploader.svc
Если вы видите что-то вроде следующего изображения, вы готовы!
Б) Клиентская сторона
Я создал простое приложение, которое отправляет строку в файл на сервере.
1- Создайте приложение для Windows Phone. Я предполагаю, что вы знаете, как сделать этот шаг.
2. Клиент службы WCF FileUploader необходимо добавить в проект. Щелкните правой кнопкой мыши по проекту Windows Phone и выберите «Добавить ссылку на службу».
— Введите адрес вашего сервиса WCF. В этом примере это http://www.ultimatepokermanager.com/upm/servertest/FileUploader.svc
— переименуйте пространство имен в FileUploader.
— Нажмите ОК.
3- Замените содержимое MainPage.xaml следующим:
<phone:PhoneApplicationPage x:Class="SendFileApp.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignWidth="480"
d:DesignHeight="800"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Margin="12,17,0,28">
<TextBlock Text="SEND FILE"
Style="{StaticResource PhoneTextNormalStyle}" />
<TextBlock Text="dashboard"
Margin="9,-7,0,0"
Style="{StaticResource PhoneTextTitle1Style}" />
</StackPanel>
<StackPanel Grid.Row="1"
Margin="12,0,12,0">
<TextBlock Margin="12,0,0,0"
Text="Content" />
<TextBox Text="abcdefg"
x:Name="textBoxContent" />
<TextBlock Margin="12,0,0,0"
Text="File name" />
<TextBox Text="Sample.txt"
x:Name="textBoxFileName" />
<Button Content="Send File"
Click="ButtonSendFile" />
<Button Content="Download File"
Click="ButtonDownloadFile"
IsEnabled="False"
x:Name="buttonDownloadFile"/>
</StackPanel>
</Grid>
</phone:PhoneApplicationPage>
Этот контент использует только стандартные элементы управления.
4- Замените содержимое MainPage.xaml.cs на:
using System;
using System.Net;
using System.Text;
using System.Windows;
using SendFileApp.FileUploader;
namespace SendFileApp
{
public partial class MainPage
{
#region Constants
// For this sample, the uploaded file can be access from my public folder
private const string PublicServer = "http://www.ultimatepokermanager.com/upm/ServerTest/backup";
#endregion
#region Fields
private string _directory;
#endregion
#region Constructor
public MainPage()
{
InitializeComponent();
}
#endregion
#region Event Handlers
private void ButtonSendFile(object sender, RoutedEventArgs e)
{
byte[] content = Encoding.UTF8.GetBytes(textBoxContent.Text);
_directory = Guid.NewGuid().ToString();
FileUploaderClient fileUploaderClient = new FileUploaderClient();
fileUploaderClient.UploadCompleted += UploadCompleted;
fileUploaderClient.UploadAsync(new UploadFile { RelativeDirectory = string.Format("/{0}", _directory), FileName = textBoxFileName.Text, Content = content });
}
private void UploadCompleted(object sender, UploadCompletedEventArgs uploadCompletedEventArgs)
{
buttonDownloadFile.IsEnabled = true;
if (uploadCompletedEventArgs.Result == null)
{
MessageBox.Show("The file has been successfully uploaded.", "Success!", MessageBoxButton.OK);
}
else
{
MessageBox.Show(string.Format("An error occured:\n\n{0}", uploadCompletedEventArgs.Result), "Error", MessageBoxButton.OK);
}
}
private void ButtonDownloadFile(object sender, RoutedEventArgs e)
{
WebClient webClient = new WebClient();
webClient.DownloadStringCompleted += WebClientDownloadStringCompleted;
webClient.DownloadStringAsync(new Uri(string.Format("{0}/{1}/{2}", PublicServer, _directory, textBoxFileName.Text)));
}
private void WebClientDownloadStringCompleted(object sender, DownloadStringCompletedEventArgs downloadStringCompletedEventArgs)
{
if (downloadStringCompletedEventArgs.Error == null)
{
MessageBox.Show(string.Format("The content of your file is:\n\n{0}", downloadStringCompletedEventArgs.Result), "Success!", MessageBoxButton.OK);
}
else
{
MessageBox.Show(string.Format("An error occured:\n{0}", downloadStringCompletedEventArgs.Error), "Error", MessageBoxButton.OK);
}
}
#endregion
}
}
Интересная часть в предыдущем коде:
private void ButtonSendFile(object sender, RoutedEventArgs e)
{
byte[] content = Encoding.UTF8.GetBytes(textBoxContent.Text);
_directory = Guid.NewGuid().ToString();
FileUploaderClient fileUploaderClient = new FileUploaderClient();
fileUploaderClient.UploadCompleted += UploadCompleted;
fileUploaderClient.UploadAsync(new UploadFile { RelativeDirectory = string.Format("/{0}", _directory), FileName = textBoxFileName.Text, Content = content });
}
Использование FileUploaderClient действительно просто:
1- Создайте экземпляр FileUploaderClient.
2- Прослушивание события UploadCompleted.
3- Загрузите файл асинхронно.
Обратите внимание, что для UploadFile нужны свойства RelativeDirectory (который начинается с «/»), FileName и Content в массиве байтов.
Пример адреса загруженного файла: http://www.ultimatepokermanager.com/upm/ServerTest/ backup /a5a8ae0b-50f0-4d16-90da-e83d6e1d30a3/Sample.txt . Вы можете увидеть каталог резервных копий, ранее установленный в файле Web.config.
В этом примере я сгенерировал GUID для имени каталога. Кроме того, загруженные файлы являются общедоступными, пока пользователь (или приложение) знает об имени каталога и имени файла. Если вы хотите добавить уровень конфиденциальности, вам просто нужно внедрить метод DownloadFile в ваш сервис. Это не должно быть сложно, если вы читаете код метода Upload.
Я гарантирую вам, что вы будете рады видеть, когда ваш веб-сервис работает!
Скачать пример проекта





