Использование веб-службы ASP.NET (ASMX)

ASMX предоставляет возможность создавать веб-службы, отправляющие сообщения с помощью протокола SOAP. SOAP — это независимый от платформы и независимый от языка протокол для создания и доступа к веб-службам. Потребители службы ASMX не должны знать ничего о платформе, объектной модели или языке программирования, используемом для реализации службы. Им нужно только понять, как отправлять и получать сообщения SOAP. В этой статье показано, как использовать службу SOAP ASMX из Xamarin.Forms приложения.

Сообщение SOAP — это XML-документ, содержащий следующие элементы:

  • Корневой элемент с именем Envelope , который идентифицирует XML-документ как сообщение SOAP.
  • Необязательный элемент Заголовка , содержащий сведения, относящиеся к приложению, такие как данные проверки подлинности. Если элемент Header присутствует, он должен быть первым дочерним элементом элемента Envelope.
  • Обязательный элемент Body , содержащий сообщение SOAP, предназначенное для получателя.
  • Необязательный элемент fault , используемый для указания сообщений об ошибках. Если элемент Fault присутствует, он должен быть дочерним элементом элемента Body.

SOAP может работать над множеством транспортных протоколов, включая ПРОТОКОЛ HTTP, SMTP, TCP и UDP. Однако служба ASMX может работать только по протоколу HTTP. Платформа Xamarin поддерживает стандартные реализации SOAP 1.1 по протоколу HTTP, и это включает поддержку многих стандартных конфигураций служб ASMX.

Этот пример включает мобильные приложения, которые выполняются на физических или эмулированных устройствах, а также службу ASMX, которая предоставляет методы для получения, добавления, редактирования и удаления данных. При запуске мобильных приложений они подключаются к локально размещенной службе ASMX, как показано на следующем снимке экрана:

Пример приложения

Примечание.

В iOS 9 и более поздней версии безопасность транспорта приложений (ATS) обеспечивает безопасные подключения между интернет-ресурсами (например, сервером приложения) и приложением, тем самым предотвращая случайное раскрытие конфиденциальной информации. Так как ATS включен по умолчанию в приложениях, созданных для iOS 9, все подключения будут соответствовать требованиям безопасности ATS. Если подключения не соответствуют этим требованиям, они завершаются сбоем с исключением. ATS можно отказаться от использования протокола и безопасного HTTPS обмена данными для интернет-ресурсов. Это можно сделать, обновив файл Info.plist приложения. Дополнительные сведения см. в разделе "Безопасность транспорта приложений".

Использование веб-службы

Служба ASMX предоставляет следующие операции:

Операция Description Параметры
GetTodoItems Получение списка элементов задач
CreateTodoItem Создание нового элемента для выполнения Сериализованный XML TodoItem
EditTodoItem Обновление элемента задачи Сериализованный XML TodoItem
DeleteTodoItem Удаление элемента задачи Сериализованный XML TodoItem

Дополнительные сведения о модели данных, используемой в приложении, см. в разделе "Моделирование данных".

Создание прокси-сервера TodoService

Класс прокси-сервера, называемый TodoService, расширяет SoapHttpClientProtocol и предоставляет методы для взаимодействия со службой ASMX по протоколу HTTP. Прокси-сервер создается путем добавления веб-ссылки на каждый проект для конкретной платформы в Visual Studio 2019 или Visual Studio 2017. Веб-ссылка создает методы и события для каждого действия, определенного в документе языка описания веб-служб (WSDL).

Например, GetTodoItems действие службы приводит к GetTodoItemsAsync методу и GetTodoItemsCompleted событию в прокси-сервере. Созданный метод имеет тип возвращаемого значения void и вызывает GetTodoItems действие родительского SoapHttpClientProtocol класса. Когда вызываемый метод получает ответ от службы, он запускает GetTodoItemsCompleted событие и предоставляет данные ответа в свойстве события Result .

Создание реализации ISoapService

Чтобы включить общий кроссплатформенный проект для работы со службой, пример определяет ISoapService интерфейс, который следует асинхронной модели программирования задач в C#. Каждая платформа реализует ISoapService доступ к прокси-серверу для конкретной платформы. В примере используются TaskCompletionSource объекты для предоставления прокси-сервера в качестве асинхронного интерфейса задачи. Сведения об использовании TaskCompletionSource приведены в реализации каждого типа действия в разделах ниже.

SoapServiceПример:

  1. TodoService Создает экземпляр в качестве экземпляра уровня класса
  2. Создает коллекцию, вызываемую Items для хранения TodoItem объектов
  3. Указывает пользовательскую конечную точку для необязательного Url свойства в TodoService
public class SoapService : ISoapService
{
    ASMXService.TodoService todoService;
    public List<TodoItem> Items { get; private set; } = new List<TodoItem>();

    public SoapService ()
    {
        todoService = new ASMXService.TodoService ();
        todoService.Url = Constants.SoapUrl;
        ...
    }
}

Создание объектов передачи данных

Пример приложения использует TodoItem класс для моделирования данных. Чтобы сохранить TodoItem элемент в веб-службе, сначала его необходимо преобразовать в созданный TodoItem прокси-сервер. Это достигается методом ToASMXServiceTodoItem , как показано в следующем примере кода:

ASMXService.TodoItem ToASMXServiceTodoItem (TodoItem item)
{
    return new ASMXService.TodoItem {
        ID = item.ID,
        Name = item.Name,
        Notes = item.Notes,
        Done = item.Done
    };
}

Этот метод создает новый ASMService.TodoItem экземпляр и задает каждому свойству идентичное свойство из экземпляра TodoItem .

Аналогичным образом, когда данные извлекаются из веб-службы, его необходимо преобразовать из созданного TodoItem прокси-сервера в TodoItem экземпляр. Это достигается с FromASMXServiceTodoItem помощью метода, как показано в следующем примере кода:

static TodoItem FromASMXServiceTodoItem (ASMXService.TodoItem item)
{
    return new TodoItem {
        ID = item.ID,
        Name = item.Name,
        Notes = item.Notes,
        Done = item.Done
    };
}

Этот метод извлекает данные из созданного TodoItem прокси-сервера типа и задает его в только что созданном TodoItem экземпляре.

Извлечение данных

Интерфейс ISoapService ожидает, RefreshDataAsync что метод возвращает коллекцию Task элементов. TodoService.GetTodoItemsAsync Однако метод возвращает void. Чтобы удовлетворить шаблон интерфейса, необходимо вызвать GetTodoItemsAsync, подождите, пока GetTodoItemsCompleted событие будет срабатывает, и заполните коллекцию. Это позволяет возвращать допустимую коллекцию в пользовательский интерфейс.

В приведенном ниже примере создается новый TaskCompletionSourceасинхронный вызов метода RefreshDataAsync и ожидается Task предоставленный методом TaskCompletionSource. При вызове обработчика TodoService_GetTodoItemsCompleted событий он заполняет коллекцию Items и обновляет TaskCompletionSource:

public class SoapService : ISoapService
{
    TaskCompletionSource<bool> getRequestComplete = null;
    ...

    public SoapService()
    {
        ...
        todoService.GetTodoItemsCompleted += TodoService_GetTodoItemsCompleted;
    }

    public async Task<List<TodoItem>> RefreshDataAsync()
    {
        getRequestComplete = new TaskCompletionSource<bool>();
        todoService.GetTodoItemsAsync();
        await getRequestComplete.Task;
        return Items;
    }

    private void TodoService_GetTodoItemsCompleted(object sender, ASMXService.GetTodoItemsCompletedEventArgs e)
    {
        try
        {
            getRequestComplete = getRequestComplete ?? new TaskCompletionSource<bool>();

            Items = new List<TodoItem>();
            foreach (var item in e.Result)
            {
                Items.Add(FromASMXServiceTodoItem(item));
            }
            getRequestComplete?.TrySetResult(true);
        }
        catch (Exception ex)
        {
            Debug.WriteLine(@"\t\tERROR {0}", ex.Message);
        }
    }

    ...
}

Дополнительные сведения см. в статье "Асинхронная модель программирования" и TPL и традиционное платформа .NET Framework асинхронное программирование.

Создание или изменение данных

При создании или изменении данных необходимо реализовать ISoapService.SaveTodoItemAsync метод. Этот метод определяет, является ли TodoItem новый или обновленный элемент и вызывает ли соответствующий метод в объекте todoService . CreateTodoItemCompletedEditTodoItemCompleted Обработчики событий также должны быть реализованы, чтобы узнать, когда todoService получен ответ от службы ASMX (их можно объединить в один обработчик, так как они выполняют ту же операцию). В следующем примере показаны реализации интерфейса и обработчика событий, а также TaskCompletionSource объект, используемый для асинхронной работы:

public class SoapService : ISoapService
{
    TaskCompletionSource<bool> saveRequestComplete = null;
    ...

    public SoapService()
    {
        ...
        todoService.CreateTodoItemCompleted += TodoService_SaveTodoItemCompleted;
        todoService.EditTodoItemCompleted += TodoService_SaveTodoItemCompleted;
    }

    public async Task SaveTodoItemAsync (TodoItem item, bool isNewItem = false)
    {
        try
        {
            var todoItem = ToASMXServiceTodoItem(item);
            saveRequestComplete = new TaskCompletionSource<bool>();
            if (isNewItem)
            {
                todoService.CreateTodoItemAsync(todoItem);
            }
            else
            {
                todoService.EditTodoItemAsync(todoItem);
            }
            await saveRequestComplete.Task;
        }
        catch (SoapException se)
        {
            Debug.WriteLine("\t\t{0}", se.Message);
        }
        catch (Exception ex)
        {
            Debug.WriteLine("\t\tERROR {0}", ex.Message);
        }
    }

    private void TodoService_SaveTodoItemCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
    {
        saveRequestComplete?.TrySetResult(true);
    }

    ...
}

Удаление данных

Для удаления данных требуется аналогичная реализация. Определите TaskCompletionSource, реализуйте обработчик событий и ISoapService.DeleteTodoItemAsync метод:

public class SoapService : ISoapService
{
    TaskCompletionSource<bool> deleteRequestComplete = null;
    ...

    public SoapService()
    {
        ...
        todoService.DeleteTodoItemCompleted += TodoService_DeleteTodoItemCompleted;
    }

    public async Task DeleteTodoItemAsync (string id)
    {
        try
        {
            deleteRequestComplete = new TaskCompletionSource<bool>();
            todoService.DeleteTodoItemAsync(id);
            await deleteRequestComplete.Task;
        }
        catch (SoapException se)
        {
            Debug.WriteLine("\t\t{0}", se.Message);
        }
        catch (Exception ex)
        {
            Debug.WriteLine("\t\tERROR {0}", ex.Message);
        }
    }

    private void TodoService_DeleteTodoItemCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
    {
        deleteRequestComplete?.TrySetResult(true);
    }

    ...
}

Тестирование веб-службы

Для тестирования физических или эмулированных устройств с локально размещенной службой требуется настраиваемая конфигурация IIS, адреса конечных точек и правила брандмауэра. Дополнительные сведения о настройке среды для тестирования см. в разделе "Настройка удаленного доступа к IIS Express". Единственное различие между тестированием WCF и ASMX — номер порта TodoService.