Практическое руководство. Миграция веб-служб ASP.NET с поддержкой AJAX на платформу WCF

В этом разделе описаны процедуры переноса базовой службы ASP.NET AJAX в эквивалентную службу Windows Communication Foundation (WCF). В нем показано, как создать функционально эквивалентную версию WCF службы ASP.NET AJAX. Затем эти две службы можно использовать параллельно или службу WCF можно использовать для замены службы ASP.NET AJAX.

Перенос существующей службы ASP.NET AJAX в службу WCF AJAX дает следующие преимущества:

  • службу AJAX можно сделать доступной в качестве службы SOAP при минимальной дополнительной настройке;

  • Вы можете воспользоваться такими функциями WCF, как трассировка и т. д.

В следующих процедурах предполагается, что вы используете Visual Studio 2012.

Код, получаемый в результате применения описанных в этом разделе процедур, приведен в примере после процедур.

Дополнительные сведения о предоставлении службы WCF через конечную точку с поддержкой AJAX см. в разделе "Практическое руководство. Использование конфигурации для добавления ASP.NET конечной точки AJAX".

Создание и тестирование приложения веб-службы ASP.NET

  1. Откройте Visual Studio 2012.

  2. В меню "Файл" выберите "Создать", затем "Проект", а затем "Веб-приложение" и выберите ASP.NET веб-служба.

  3. Присвойте проекту ASPHello имя и нажмите кнопку "ОК".

  4. В файле Service1.asmx.cs снимите знаки комментария со строки, содержащей System.Web.Script.Services.ScriptService], чтобы включить для этой службы поддержку AJAX.

  5. В меню Построение выберите пункт Построить решение.

  6. В меню Отладка выберите Запуск без отладки.

  7. На созданной веб-странице выберите операцию HelloWorld.

  8. Нажмите кнопку "Вызвать" на тестовой HelloWorld странице. Должен появиться следующий XML-ответ.

    <?xml version="1.0" encoding="utf-8" ?>
    <string xmlns="http://tempuri.org/">Hello World</string>
    
  9. Этот ответ подтверждает, что имеется функционирующая служба AJAX ASP.NET, и что эта служба доступна через конечную точку Service1.asmx/HelloWorld, которая отвечает на запросы HTTP POST и возвращает XML-код.

    Теперь вы готовы преобразовать эту службу для использования службы WCF AJAX.

Создание эквивалентного приложения службы AJAX WCF

  1. Щелкните правой кнопкой мыши проект ASPHello и выберите "Добавить", а затем "Создать элемент" и "Служба WCF с поддержкой AJAX".

  2. Назовите службу WCFHello и нажмите кнопку "Добавить".

  3. Откройте файл WCFHello.svc.cs.

  4. Скопируйте следующую реализацию HelloWorld операции из Service1.asmx.cs.

    public string HelloWorld()
    {
        return "Hello World";
    }
    
  5. Вставьте в скопированную реализацию HelloWorld операции в файл WCFHello.svc.cs вместо следующего кода.

    public void DoWork()
    {
          // Add your operation implementation here
          return;
    }
    
  6. Namespace Укажите атрибут для ServiceContractAttribute as WCFHello.

    [ServiceContract(Namespace="WCFHello")]
    [AspNetCompatibilityRequirements(RequirementsMode=AspNetCompatibilityRequirementsMode.Required)]
    public class WCFHello
    { … }
    
  7. WebInvokeAttributeHelloWorld Добавьте операцию и задайте ResponseFormat возвращаемое Xmlсвойство. Обратите внимание, что если это свойство не задано, будет возвращаться тип Json.

    [OperationContract]
    [WebInvoke(ResponseFormat=WebMessageFormat.Xml)]
    public string HelloWorld()
    {
        return "Hello World";
    }
    
  8. В меню Построение выберите пункт Построить решение.

  9. Откройте файл WCFHello.svc и в меню отладки выберите "Пуск без отладки".

  10. Теперь служба предоставляет конечную точку, WCFHello.svc/HelloWorldкоторая отвечает на HTTP-запросы POST. Запросы HTTP POST невозможно тестировать с помощью браузера, но конечная точка возвращает следующий XML-код.

    <string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">Hello World</string>
    
  11. Конечные WCFHello.svc/HelloWorldService1.aspx/HelloWorld точки теперь функционально эквивалентны.

Пример

Код, получаемый в результате применения описанных в этом разделе процедур, приведен в следующем примере.

//This is the ASP.NET code in the Service1.asmx.cs file.

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml.Linq;
using System.Web.Script.Services;

namespace ASPHello
{
    /// <summary>
    /// Summary description for Service1.
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [ToolboxItem(false)]
    // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
    [System.Web.Script.Services.ScriptService]
    public class Service1 : System.Web.Services.WebService
    {

        [WebMethod]
        public string HelloWorld()
        {
            return "Hello World";
        }
    }
}

//This is the WCF code in the WCFHello.svc.cs file.
using System;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;

namespace ASPHello
{
    [ServiceContract(Namespace = "WCFHello")]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class WCFHello
    {
        // Add [WebInvoke] attribute to use HTTP GET.
        [OperationContract]
        [WebInvoke(ResponseFormat=WebMessageFormat.Xml)]
        public string HelloWorld()
        {
            return "Hello World";
        }

        // Add more operations here and mark them with [OperationContract].
    }
}

Тип XmlDocument не поддерживается классом DataContractJsonSerializer, потому что его невозможно сериализовать с помощью класса XmlSerializer. Можно использовать тип XDocument или сериализовать свойство DocumentElement.

Если веб-службы ASMX обновляются и переносятся параллельно в службы WCF, избегайте сопоставления двух типов с одинаковым именем на клиенте. Это приведет к исключению при сериализации, если в атрибутах WebMethodAttribute и ServiceContractAttribute будет использоваться один и тот же тип:

  • Если служба WCF добавляется сначала, вызов метода в веб-службе ASMX вызывает исключение, ConvertValue(Object, Type, String) так как определение стиля WCF порядка в прокси-сервере имеет приоритет.

  • Если веб-служба ASMX добавлена сначала, вызов метода в службе WCF вызывает исключение, DataContractJsonSerializer так как определение стиля веб-службы порядка в прокси-сервере имеет приоритет.

Имеются важные различия в работе класса DataContractJsonSerializer и класса JavaScriptSerializer AJAX ASP.NET. Например, класс DataContractJsonSerializer представляет словарь в виде массива пар "ключ-значение", а класс JavaScriptSerializer AJAX ASP.NET представляет словарь в виде фактических объектов JSON. Ниже представлен словарь в формате AJAX ASP.NET.

Dictionary<string, int> d = new Dictionary<string, int>();
d.Add("one", 1);
d.Add("two", 2);

Этот словарь состоит из объектов JSON, как показано в следующем списке:

Класс DataContractJsonSerializer обладает более широкими возможностями в том смысле, что он может обрабатываться словари, где тип ключа не является строковым; класс JavaScriptSerializer не поддерживает такой возможности. Однако последний класс лучше работает с форматом JSON.

Ключевые различия между этими сериализаторами показаны в следующей таблице.

Категория различий DataContractJsonSerializer JavaScriptSerializer AJAX ASP.NET
Десериализация пустого буфера (new byte[0]) в Object (или Uri, или некоторые другие классы). SerializationException null
Сериализация Value {} (или {"__type":"#System"}) Null
Сериализация закрытых членов типов [Serializable] Сериализуются Не сериализуются
Сериализация открытых свойств типов ISerializable Не сериализуются Сериализуются
Расширения JSON Удовлетворяет спецификации JSON, которая требует заключать имена членов объектов в кавычки ({"a":"hello"}). Поддерживает имена членов объектов без кавычек ({a:"hello"}).
Время в формате UTC (DateTime) Не поддерживает формат "\/Date(123456789U)\/" или "\/Date\(\d+(U|( \+\-[\d{4}])?\)\)". Поддерживает формат "\/Date(123456789U)\/" и "\/Date\(\d+(U|( \+\-[\d{4}])?\)\\\)" в качестве значений DateTime.
Представление словарей Массив KeyValuePair<K,V> обрабатывает типы ключей, которые не являются строками. Фактические объекты JSON, но обрабатывает только ключи строковых типов
Escape-символы Всегда с escape-символом прямой косой черты (/); нельзя использовать недопустимые символы JSON без escape-символа, например "\n" Значения DateTime с escape-символом прямой косой черты (/)

См. также