Вот полное пошаговое руководство по созданию службы резервного копирования 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.
Я гарантирую вам, что вы будете рады видеть, когда ваш веб-сервис работает!
Скачать пример проекта