Поделиться через


Сравнение веб-служб ASP.NET с веб-службами на основе WCF по процессу разработки

Windows Communication Foundation (WCF) имеет параметр режима совместимости ASP.NET, чтобы обеспечить программирование и настройку приложений WCF, таких как ASP.NET веб-службы, имитировать их поведение. В следующих разделах сравниваются ASP.NET веб-службы и WCF на основе того, что необходимо для разработки приложений с помощью обоих технологий.

Представление данных

Разработка веб-службы с помощью ASP.NET обычно начинается с определения сложных типов данных, которые будет использовать служба. ASP.NET предполагает использование сериализатора XmlSerializer для преобразования представленных типами .NET Framework данных в XML для передачи службе или от службы и для преобразования полученных в виде XML данных в объекты .NET Framework. Определение сложных типов данных, которые будет использовать служба ASP.NET, требует определения классов .NET Framework, которые XmlSerializer может сериализовать в XML и из XML. Такие классы могут быть написаны вручную или сформированы из определений типов в схеме XML с помощью утилиты командной строки для поддержки схем XML/типов данных (xsd.exe).

Ниже перечислены основные моменты, которые необходимо знать для определения классов .NET Framework, которые XmlSerializer сможет сериализовать в XML и из XML.

  • В XML преобразуются только открытые поля и свойства объектов .NET Framework.

  • Экземпляры классов коллекций могут быть сериализованы в XML только при условии реализации классами интерфейса IEnumerable или ICollection.

  • Классы, реализующие интерфейс IDictionary, такие как Hashtable, не могут быть сериализованы в XML.

  • Пространство имен System.Xml.Serialization содержит огромное множество типов атрибутов, которые можно добавлять в классы .NET Framework и их члены для управления тем, как экземпляры класса будут представлены в XML.

Разработка приложений WCF обычно начинается с определения сложных типов. WCF можно использовать те же платформа .NET Framework типы, что и веб-службы ASP.NET.

WCFDataContractAttribute и DataMemberAttribute может быть добавлен в типы платформа .NET Framework, чтобы указать, что экземпляры типа должны быть сериализованы в XML, и какие определенные поля или свойства типа должны быть сериализованы, как показано в следующем примере кода.

//Example One:
[DataContract]
public class LineItem
{
    [DataMember]
    public string ItemNumber;
    [DataMember]
    public decimal Quantity;
    [DataMember]
    public decimal UnitPrice;
}

//Example Two:
public class LineItem
{
    [DataMember]
    private string itemNumber;
    [DataMember]
    private decimal quantity;
    [DataMember]
    private decimal unitPrice;

    public string ItemNumber
    {
      get
      {
          return this.itemNumber;
      }

      set
      {
          this.itemNumber = value;
      }
    }

    public decimal Quantity
    {
        get
        {
            return this.quantity;
        }

        set
        {
            this.quantity = value;
        }
    }

    public decimal UnitPrice
    {
      get
      {
          return this.unitPrice;
      }

      set
      {
          this.unitPrice = value;
      }
    }
}

//Example Three:
public class LineItem
{
     private string itemNumber;
     private decimal quantity;
     private decimal unitPrice;

     [DataMember]
     public string ItemNumber
     {
       get
       {
          return this.itemNumber;
       }

       set
       {
           this.itemNumber = value;
       }
     }

     [DataMember]
     public decimal Quantity
     {
          get
          {
              return this.quantity;
          }

          set
          {
             this.quantity = value;
          }
     }

     [DataMember]
     public decimal UnitPrice
     {
          get
          {
              return this.unitPrice;
          }

          set
          {
              this.unitPrice = value;
          }
     }
}

Атрибут DataContractAttribute означает, что ноль или более полей или свойств типа должны быть сериализованы, тогда как атрибут DataMemberAttribute указывает, что определенное поле или свойство должно быть сериализовано. Атрибут DataContractAttribute может быть применен к классу или структуре. Атрибут DataMemberAttribute может быть применен к полю или свойству, причем поля и свойства, к которым применяется атрибут, могут быть как открытыми, так и закрытыми. Экземпляры типов, DataContractAttribute применяемых к ним, называются контрактами данных в WCF. Они сериализуются в XML с помощью сериализатора DataContractSerializer.

Ниже перечислены важные различия между использованием сериализатора DataContractSerializer и использованием сериализатора XmlSerializer и различных атрибутов из пространства имен System.Xml.Serialization.

  • Сериализатор XmlSerializer и атрибуты из пространства имен System.Xml.Serialization предназначены для того, чтобы разработчик мог сопоставлять типы .NET Framework с любым допустимым типом, определенным в схеме XML, и как таковые позволяют очень точно управлять тем, как тип будет представлен в XML. Сериализатор DataContractSerializer и атрибуты DataContractAttribute и DataMemberAttribute позволяют контролировать представление типа в XML в очень небольшой степени. Можно указать только пространства имен и имена, используемые для представления типа и его полей или свойств в XML, а также последовательности, в которой поля и свойства будут идти в XML.

    [DataContract(
    Namespace="urn:Contoso:2006:January:29",
    Name="LineItem")]
    public class LineItem
    {
          [DataMember(Name="ItemNumber",IsRequired=true,Order=0)]
          public string itemNumber;
          [DataMember(Name="Quantity",IsRequired=false,Order = 1)]
          public decimal quantity;
          [DataMember(Name="Price",IsRequired=false,Order = 2)]
          public decimal unitPrice;
    }
    

    Все остальные аспекты структуры XML-данных, используемых для представления типа .NET, определяет DataContractSerializer.

  • Благодаря ограниченности контроля разработчика над представлением типа в XML процесс сериализации с помощью DataContractSerializer весьма предсказуем и, следовательно, его легче оптимизировать. Практическое преимущество такого принципа работы DataContractSerializer состоит в повышении производительности примерно на десять процентов.

  • Атрибуты, предназначенные для использования в сочетании с сериализатором XmlSerializer, не указывают, какие поля или свойства сериализуются в XML, тогда как атрибут DataMemberAttribute, предназначенный для использования в сочетании с сериализатором DataContractSerializer, явно показывает, какие поля или свойства сериализуются. Следовательно, контракты данных представляют собой явные контракты о структуре данных, которые будет отправлять и получать приложение.

  • Сериализатор XmlSerializer может преобразовывать в XML только открытые члены объекта .NET; сериализатор DataContractSerializer может преобразовывать в XML члены объектов независимо от модификаторов доступа этих членов.

  • Вследствие способности сериализовать в XML закрытые члены типов для сериализатора DataContractSerializer характерно меньшее количество ограничений на типы .NET, которые он может сериализовать в XML. В частности, он способен преобразовывать в XML такие типы, как Hashtable, который реализует интерфейс IDictionary. Сериализатор DataContractSerializer со значительно большей вероятностью сможет сериализовать в XML экземпляры любого уже существующего типа .NET без внесения в тип изменений или разработки для него оболочки.

  • Другим следствием способности сериализатора DataContractSerializer получать доступ к закрытым членам типа является то, что ему требуется полное доверие, тогда как сериализатор XmlSerializer этого не требует. Разрешение на доступ к коду полного доверия предоставляет полный доступ ко всем ресурсам на компьютере, к которым можно получить доступ с помощью учетных данных, под которым выполняется код. Этот параметр следует использовать с осторожностью, так как полностью доверенный код обращается ко всем ресурсам на компьютере.

  • Сериализатор DataContractSerializer предусматривает некоторую поддержку управления версиями.

    • Атрибут DataMemberAttribute имеет свойство IsRequired, которому можно присваивать значение false для добавляемых в новые версии (т. е. отсутствовавших в предыдущих версиях) контракта данных членов, что позволяет приложениям с более новой версией контракта обрабатывать более ранние версии типа.

    • Реализуя в контракте данных интерфейс IExtensibleDataObject, разработчик может позволить сериализатору DataContractSerializer передавать члены, определенные в более новых версиях контракта данных, через приложения с более ранними версиями контракта.

Несмотря на все различия, XML-данные, в которые XmlSerializer сериализует тип, по умолчанию семантически идентичны XML-данным, в которые сериализует тип DataContractSerializer, при условии, что пространство имен для XML определено явным образом. Следующий класс, имеющий атрибуты для использования с обоими сериализаторами, преобразуется в семантически идентичный XML с помощью XmlSerializerDataContractAttribute:

[Serializable]
[XmlRoot(Namespace="urn:Contoso:2006:January:29")]
[DataContract(Namespace="urn:Contoso:2006:January:29")]
public class LineItem
{
     [DataMember]
     public string ItemNumber;
     [DataMember]
     public decimal Quantity;
     [DataMember]
     public decimal UnitPrice;
}

Пакет средств разработки программного обеспечения Windows (SDK) включает в себя средство командной строки, называемое средством служебной программы метаданных ServiceModel (Svcutil.exe). Как и средство xsd.exe, используемое с веб-службами ASP.NET, Svcutil.exe может создавать определения типов данных .NET из схемы XML. Типы являются контрактами данных, если сериализатор DataContractSerializer способен выдать XML-данные в формате, определенном схемой XML; в противном случае они предназначены для сериализации с помощью XmlSerializer. Svcutil.exe также может создавать XML-схему из контрактов данных с помощью его dataContractOnly коммутатора.

Примечание.

Хотя веб-службы ASP.NET используют XmlSerializerрежим совместимости , а режим совместимости WCF ASP.NET позволяет службам WCF имитировать поведение веб-служб ASP.NET, параметр совместимости ASP.NET не ограничивает использование.XmlSerializer Сериализатор DataContractSerializer можно использовать и для служб, выполняемых в режиме совместимости с ASP.NET.

Разработка служб

Для разработки службы с использованием ASP.NET обычно требовалось добавлять атрибут WebService в класс и атрибут WebMethodAttribute во все методы этого класса, которые являются операциями службы:

[WebService]
public class Service : T:System.Web.Services.WebService
{
    [WebMethod]
    public string Echo(string input)
    {
       return input;
    }
}

В ASP.NET 2.0 появилась возможность добавления атрибутов WebService и WebMethodAttribute в интерфейс, а не в класс, и написания класса для реализации этого интерфейса:

[WebService]
public interface IEcho
{
    [WebMethod]
    string Echo(string input);
}

public class Service : IEcho
{

   public string Echo(string input)
   {
        return input;
    }
}

Этот вариант является предпочтительным, так как интерфейс с атрибутом WebService составляет контракт для операций, выполняемых службой, доступный для повторного использования в различных классах, которые могут реализовывать этот же контракт другими способами.

Служба WCF предоставляется путем определения одной или нескольких конечных точек WCF. Конечная точка определяется адресом, привязкой и контрактом службы. Адрес определяет местонахождение службы. Привязка задает способ обмена данными со службой. Контракт службы определяет операции, которые может выполнять служба.

Контракт службы обычно определяется в первую очередь, путем добавления атрибутов ServiceContractAttribute и OperationContractAttribute в интерфейс:

[ServiceContract]
public interface IEcho
{
     [OperationContract]
     string Echo(string input);
}

Указывает ServiceContractAttribute , что интерфейс определяет контракт службы WCF и OperationContractAttribute указывает, какие методы интерфейса определяют операции контракта службы.

После определения контракта службы он реализуется в классе - путем реализации в классе интерфейса, которым определяется контракт службы:

public class Service : IEcho
{
    public string Echo(string input)
    {
       return input;
    }
}

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

Следующий шаг - связать адрес и привязку с типом службы. Обычно это делается в файле конфигурации путем непосредственного редактирования файла или с помощью редактора конфигурации, предоставленного WCF. Ниже приведен пример файла конфигурации.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
     <system.serviceModel>
      <services>
      <service name="Service ">
       <endpoint
        address="EchoService"
        binding="basicHttpBinding"
        contract="IEchoService "/>
      </service>
      </services>
     </system.serviceModel>
</configuration>

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

Имя. Характер использования
BasicHttpBinding Взаимодействие с веб-службами и клиентами, поддерживающими спецификации WS-BasicProfile 1.1 и Basic Security Profile 1.0.
WSHttpBinding Взаимодействие с веб-службами и клиентами, поддерживающими протоколы WS-* через HTTP.
WSDualHttpBinding Дуплексная связь по протоколу HTTP, при которой получатель первоначального сообщения не отвечает непосредственно первоначальному отправителю, но может передавать любое количество ответов в течение некоторого периода времени, используя HTTP в соответствии с протоколами WS-*.
WSFederationBinding Связь по протоколу HTTP, при которой доступом к ресурсам службы можно управлять на основе учетных данных, выданных явно идентифицированным поставщиком учетных данных.
NetTcpBinding Безопасное, надежное и высокопроизводительное взаимодействие между сущностями программного обеспечения WCF в сети.
NetNamedPipeBinding Безопасная, надежная, высокопроизводительная связь между сущностями программного обеспечения WCF на одном компьютере.
NetMsmqBinding Обмен данными между сущностями программного обеспечения WCF с помощью MSMQ.
MsmqIntegrationBinding Обмен данными между сущностью программного обеспечения WCF и другой сущностью программного обеспечения с помощью MSMQ.
NetPeerTcpBinding Обмен данными между сущностями программного обеспечения WCF с помощью одноранговых сетей Windows.

Предоставляемая системой привязка BasicHttpBinding включает набор протоколов, поддерживаемых веб-службами ASP.NET.

Пользовательские привязки для приложений WCF легко определяются как коллекции классов элементов привязки, которые WCF использует для реализации отдельных протоколов. Можно писать новые элементы привязки для представления дополнительных протоколов.

Внутреннее поведение типов служб можно корректировать, используя свойства семейства классов, называемых поведениями. В следующем примере с помощью класса ServiceBehaviorAttribute указывается, что тип службы должен быть многопоточным.

[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Multiple)]
public class DerivativesCalculatorServiceType: IDerivativesCalculator

Некоторые поведения, такие как ServiceBehaviorAttribute, представляют собой атрибуты. Другие, имеющие свойства, которые может потребоваться задавать администраторам, могут быть изменены в конфигурации приложения.

При программировании типов служб часто используется класс OperationContext. Его статическое свойство Current обеспечивает доступ к информации о контексте, в котором выполняется операция. OperationContext аналогичен классам HttpContext и ContextUtil.

Размещение на компьютере

Веб-службы ASP.NET компилируются в сборку библиотеки классов. Формируется файл, называемый файлом службы, который имеет расширение ASMX и содержит директиву @ WebService. Эта директива идентифицирует класс, содержащий код для службы и сборку, в которой он находится.

<%@ WebService Language="C#" Class="Service,ServiceAssembly" %>

Файл службы копируется в корень приложения ASP.NET в службах IIS, а сборка копируется в подкаталог \bin этого корня приложения. После этого приложение будет доступно по URL-адресу файла службы в корне приложения.

Службы WCF можно легко размещать в службах IIS 5.1 или 6.0, службе активации процессов Windows (WAS), которая предоставляется в составе IIS 7.0 и в любом приложении .NET. Чтобы службу можно было разместить в IIS 5.1 или 6.0, в качестве транспортного протокола связи она должна использовать HTTP.

Чтобы разместить службу в IIS 5.1, 6.0 или в WAS, выполните следующие действия.

  1. Скомпилируйте тип службы в сборку библиотеки классов.

  2. Создайте файл службы с расширением SVC с директивой @ ServiceHost для идентификации типа службы:

    <%@ServiceHost language="c#" Service="MyService" %>

  3. Скопируйте файл службы в виртуальный каталог, а сборку в подкаталог \bin этого виртуального каталога.

  4. Скопируйте файл конфигурации в виртуальный каталог и назовите его Web.config.

После этого приложение будет доступно по URL-адресу файла службы в корне приложения.

Чтобы разместить службу WCF в приложении .NET, скомпилируйте тип службы в сборку библиотеки классов, на которую ссылается приложение, и программируйте приложение для размещения службы с помощью ServiceHost класса. Ниже приведен простой пример требуемого программирования:

string httpBaseAddress = "http://www.contoso.com:8000/";
string tcpBaseAddress = "net.tcp://www.contoso.com:8080/";

Uri httpBaseAddressUri = new Uri(httpBaseAddress);
Uri tcpBaseAddressUri = new Uri(tcpBaseAddress);

Uri[] baseAddresses = new Uri[] {
 httpBaseAddressUri,
 tcpBaseAddressUri};

using(ServiceHost host = new ServiceHost(
typeof(Service), //"Service" is the name of the service type baseAddresses))
{
     host.Open();

     […] //Wait to receive messages
     host.Close();
}

В этом примере показано задание адресов для одного или нескольких транспортных протоколов при построении объекта ServiceHost. Эти адреса называются базовыми адресами.

Адрес, предоставленный для любой конечной точки службы WCF, является адресом относительно базового адреса узла конечной точки. Узел размещения может иметь по одному базовому адресу для каждого транспортного протокола связи. В приведенном выше примере файла конфигурации выбранная для конечной точки привязка BasicHttpBinding предполагает использование в качестве транспорта протокола HTTP, поэтому адрес конечной точки — EchoService— рассматривается относительно базового HTTP-адреса узла. В случае узла в предыдущем примере базовый адрес HTTP является http://www.contoso.com:8000/. Для службы, размещенной в IIS или WAS, базовый адрес - это URL-адрес файла службы для этой службы.

Для использования параметра режима совместимости WC ASP.NET F можно использовать только службы, размещенные в СЛУЖБАх IIS или WAS, и настроенные с использованием протокола HTTP в качестве исключительно транспортного протокола. Для включения этого режима необходимо выполнить следующие шаги.

  1. Программист должен добавить атрибут AspNetCompatibilityRequirementsAttribute в тип службы и указать, что режим совместимости с ASP.NET допускается либо требуется.

    [System.ServiceModel.Activation.AspNetCompatibilityRequirements(
          RequirementsMode=AspNetCompatibilityRequirementsMode.Require)]
    public class DerivativesCalculatorServiceType: IDerivativesCalculator
    
  2. Администратор должен настроить приложение на использование режима совместимости с ASP.NET.

    <configuration>
         <system.serviceModel>
          <services>
          […]
          </services>
          <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
        </system.serviceModel>
    </configuration>
    

    Приложения WCF также можно настроить для использования ASMX в качестве расширения для файлов службы, а не SVC.

    <system.web>
         <compilation>
          <compilation debug="true">
          <buildProviders>
           <remove extension=".asmx"/>
           <add extension=".asmx"
            type="System.ServiceModel.ServiceBuildProvider,
            System.ServiceModel,
            Version=3.0.0.0,
            Culture=neutral,
            PublicKeyToken=b77a5c561934e089" />
          </buildProviders>
          </compilation>
         </compilation>
    </system.web>
    

    Этот параметр позволяет сэкономить от необходимости изменять клиенты, настроенные для использования URL-адресов файлов службы ASMX при изменении службы для использования WCF.

Разработка клиентов

Клиенты для веб-служб ASP.NET формируются с помощью программы командной строки WSDL.exe, которая предоставляет URL-адрес ASMX-файла в качестве входных данных. Соответствующее средство, предоставляемое WCF, — это средство служебной программы метаданных ServiceModel (Svcutil.exe). Он создает модуль кода с определением контракта службы и определением клиентского класса WCF. Кроме того, она формирует файл конфигурации с адресом и привязкой службы.

При программировании клиента удаленной службы обычно рекомендуется программировать в соответствии с асинхронной моделью. Код, формируемый программой WSDL.exe, по умолчанию всегда предусматривает и синхронную, и асинхронную модели. Код, созданный средством служебной программы метаданных ServiceModel (Svcutil.exe), может содержать любой шаблон. По умолчанию предусматривается синхронная модель. При выполнении программы с переключателем /async сформированный код предусматривает асинхронную модель.

По умолчанию имена в клиентских классах WCF, созданных средством WSDL.exe ASP.NET, по умолчанию не соответствуют именам в клиентских классах WCF, созданных средством Svcutil.exe. В частности, имена свойств классов, которые должны сериализоваться с помощью сериализатора XmlSerializer, в формируемом программой Svcutil.exe коде по умолчанию получают суффикс "Property", который отсутствует в коде, формируемом WSDL.exe.

Представление сообщений

Заголовки сообщений SOAP, отправляемых и получаемых веб-службами ASP.NET, можно настроить. Из класса SoapHeader наследуется класс для определения структуры заголовка, после чего применяется атрибут SoapHeaderAttribute, чтобы указать на присутствие заголовка.

public class SomeProtocol : SoapHeader
{
     public long CurrentValue;
     public long Total;
}

[WebService]
public interface IEcho
{
     SomeProtocol ProtocolHeader
     {
      get;
     set;
     }

     [WebMethod]
     [SoapHeader("ProtocolHeader")]
     string PlaceOrders(PurchaseOrderType order);
}

public class Service: WebService, IEcho
{
     private SomeProtocol protocolHeader;

     public SomeProtocol ProtocolHeader
     {
         get
         {
              return this.protocolHeader;
         }

         set
         {
              this.protocolHeader = value;
         }
     }

     string PlaceOrders(PurchaseOrderType order)
     {
         long currentValue = this.protocolHeader.CurrentValue;
     }
}

WCF предоставляет атрибуты, MessageContractAttributeа MessageHeaderAttributeтакже MessageBodyMemberAttribute описывает структуру отправленных и полученных службой сообщений SOAP.

[DataContract]
public class SomeProtocol
{
     [DataMember]
     public long CurrentValue;
     [DataMember]
     public long Total;
}

[DataContract]
public class Item
{
     [DataMember]
     public string ItemNumber;
     [DataMember]
     public decimal Quantity;
     [DataMember]
     public decimal UnitPrice;
}

[MessageContract]
public class ItemMessage
{
     [MessageHeader]
     public SomeProtocol ProtocolHeader;
     [MessageBody]
     public Item Content;
}

[ServiceContract]
public interface IItemService
{
     [OperationContract]
     public void DeliverItem(ItemMessage itemMessage);
}

Этот синтаксис дает явное представление структуры сообщений, тогда как в веб-службе ASP.NET структура сообщений подразумевается в коде. Кроме того, в синтаксисе ASP.NET заголовки сообщений представлены как свойства службы, например свойство в предыдущем примере, в то время как ProtocolHeader в синтаксисе WCF они более точно представлены как свойства сообщений. Кроме того, WCF позволяет добавлять заголовки сообщений в конфигурацию конечных точек.

<service name="Service ">
     <endpoint
      address="EchoService"
      binding="basicHttpBinding"
      contract="IEchoService ">
      <headers>
      <dsig:X509Certificate
       xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
       ...
      </dsig:X509Certificate>
      </headers>
     </endpoint>
</service>

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

Описание службы

При выдаче запроса HTTP-GET на ASMX-файл веб-службы ASP.NET с запросом "WSDL" ASP.NET формирует WSDL-код для описания службы. Этот WSDL-код возвращается в качестве ответа на запрос HTTP-GET.

В ASP.NET 2.0 появилась возможность проверять, совместима ли служба со спецификацией Basic Profile 1.1 Организации по обеспечению взаимодействия веб-служб (Web Services-Interoperability Organization, WS-I), и вставлять утверждение о совместимости службы в WSDL. Это делается с помощью параметров ConformsTo и EmitConformanceClaims атрибута WebServiceBindingAttribute.

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(
     ConformsTo = WsiProfiles.BasicProfile1_1,
     EmitConformanceClaims=true)]
public interface IEcho

WSDL-код, формируемый ASP.NET для службы, можно настраивать. Настройка производится путем создания класса, производного от ServiceDescriptionFormatExtension, для добавления элементов в WSDL-код.

Выдача HTTP-запроса GET с запросом WSDL для SVC-файла службы WCF с конечной точкой HTTP, размещенной в IIS 51, 6.0 или WAS, приводит к тому, что WCF отвечает с помощью WSDL, чтобы описать службу. Передача запроса HTTP-GET с запросом «WSDL» на базовый HTTP-адрес службы, размещенной в приложении .NET, имеет тот же эффект, если параметр httpGetEnabled имеет значение true.

Тем не менее WCF также отвечает на запросы WS-MetadataExchange с помощью WSDL, который он создает для описания службы. Веб-службы ASP.NET не располагают встроенной поддержкой запросов WS-MetadataExchange.

WSDL, создаваемый WCF, может быть широко настроен. Класс ServiceMetadataBehavior предоставляет некоторые средства для настройки WSDL-кода. WCF также можно настроить не для создания WSDL, а для использования статического WSDL-файла по указанному URL-адресу.

<behaviors>
     <behavior name="DescriptionBehavior">
     <metadataPublishing
      enableMetadataExchange="true"
      enableGetWsdl="true"
      enableHelpPage="true"
      metadataLocation=
      "http://localhost/DerivativesCalculatorService/Service.WSDL"/>
     </behavior>
</behaviors>

Обработка исключений.

В веб-службах ASP.NET необработанные исключения возвращаются клиентам в виде ошибок SOAP. Также можно явно вызывать исключения класса SoapException, что позволяет в большей степени контролировать содержимое ошибки SOAP, передаваемое клиенту.

В службах WCF необработанные исключения не возвращаются клиентам в виде ошибок SOAP, чтобы предотвратить непреднамеренное предоставление конфиденциальной информации через исключения. Предусмотрен параметр конфигурации для возвращения необработанных исключений клиентам в целях отладки.

Для возвращения ошибок SOAP клиентам можно вызывать исключения универсального типа - FaultException<TDetail> - используя в качестве универсального типа тип контракта данных. Также можно добавлять в операции атрибуты FaultContractAttribute для указания того, какие ошибки могут быть выданы операцией.

[DataContract]
public class MathFault
{
     [DataMember]
     public string operation;
     [DataMember]
     public string problemType;
}

[ServiceContract]
public interface ICalculator
{
     [OperationContract]
     [FaultContract(typeof(MathFault))]
     int Divide(int n1, int n2);
}

В этом случае возможные ошибки объявляются в WSDL-коде для службы, что дает разработчикам клиентов возможность предвидеть, какие ошибки могут произойти в результате операции, и написать соответствующие инструкции catch.

try
{
     result = client.Divide(value1, value2);
}
catch (FaultException<MathFault> e)
{
 Console.WriteLine("FaultException<MathFault>: Math fault while doing "
  + e.Detail.operation
  + ". Problem: "
  + e.Detail.problemType);
}

Управление данными о состоянии

Класс, используемый для реализации веб-службы ASP.NET, может наследоваться от класса WebService.

public class Service : WebService, IEcho
{

 public string Echo(string input)
 {
  return input;
 }
}

В этом случае класс можно запрограммировать на использование свойства Context базового класса WebService для доступа к объекту HttpContext. Объект HttpContext можно использовать для обновления и извлечения информации о состоянии приложения (с помощью его свойства Application) и для обновления и извлечения информации о состоянии сеанса (с помощью его свойства Session).

ASP.NET позволяет в значительной степени контролировать место фактического хранения информации о состоянии сеанса, для доступа к которой используется свойство Session объекта HttpContext. Эта информация может храниться в файлах cookie, в базе данных, в памяти текущего сервера или в памяти указанного сервера. Место хранения информации указывается в файле конфигурации службы.

WCF предоставляет расширяемые объекты для управления состоянием. Расширяемые объекты - это объекты, реализующие интерфейс IExtensibleObject<T>. Наиболее важными из расширяемых объектов являются ServiceHostBase и InstanceContext. ServiceHostBase позволяет сохранять состояние, к которому могут обращаться все экземпляры всех типов служб на одном и том же узле, тогда как InstanceContext позволяет сохранять состояние, к которому может обращаться любой код, выполняемый в одном экземпляре типа службы.

Здесь тип службы имеет значениеServiceBehaviorAttribute, TradingSystemуказывающее, что все вызовы из одного экземпляра клиента WCF направляются в один и тот же экземпляр типа службы.

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class TradingSystem: ITradingService

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

internal class DealData: IExtension<InstanceContext>
{
 public string DealIdentifier = null;
 public Trade[] Trades = null;
}

В коде типа службы, реализующем одну из операций контракта службы, к состоянию текущего экземпляра типа службы добавляется объект состояния DealData.

string ITradingService.BeginDeal()
{
 string dealIdentifier = Guid.NewGuid().ToString();
 DealData state = new DealData(dealIdentifier);
 OperationContext.Current.InstanceContext.Extensions.Add(state);
 return dealIdentifier;
}

Этот объект состояния затем может быть извлечен и изменен кодом, реализующим другую операцию контракта службы.

void ITradingService.AddTrade(Trade trade)
{
 DealData dealData =  OperationContext.Current.InstanceContext.Extensions.Find<DealData>();
 dealData.AddTrade(trade);
}

В то время как ASP.NET обеспечивает контроль над тем, где фактически хранятся сведения о состоянии в HttpContext классе, WCF, по крайней мере в его начальной версии, не обеспечивает контроля над хранением расширяемых объектов. Это является самой лучшей причиной выбора режима совместимости ASP.NET для службы WCF. Если настраиваемое управление состоянием является обязательным условием, выбор режима совместимости с ASP.NET позволяет использовать средства класса HttpContext в точности так, как они используются в ASP.NET, а также настраивать место хранения информации о состоянии с помощью класса HttpContext.

Безопасность

Для защиты веб-служб ASP.NET используются те же механизмы, что и для защиты любого приложения IIS. Так как приложения WCF могут размещаться не только в службах IIS, но и в любом исполняемом файле .NET, параметры защиты приложений WCF должны быть сделаны независимо от объектов IIS. Однако средства, предоставляемые для веб-служб ASP.NET, также доступны для служб WCF, работающих в режиме совместимости ASP.NET.

Безопасность: проверка подлинности

Службы IIS предоставляют средства для управления доступом к приложениям, позволяющие выбрать либо анонимный доступ, либо один из ряда режимов проверки подлинности: проверка подлинности Windows, дайджест-проверка подлинности, обычная проверка подлинности и проверка подлинности по паспорту .NET Passport. Вариант с проверкой подлинности Windows можно использовать для управления доступом к веб-службам ASP.NET. Однако, если приложения WCF размещаются в СЛУЖБАх IIS, службы IIS должны быть настроены для разрешения анонимного доступа к приложению, чтобы проверка подлинности была управляемой самим WCF, которая поддерживает проверка подлинности Windows среди различных других вариантов. Другие встроенные средства включают маркеры имени пользователя, сертификаты X.509, маркеры SAML и карту CardSpace; также можно определять пользовательские механизмы проверки подлинности.

Безопасность: олицетворение

ASP.NET предоставляет элемент удостоверения, посредством которого веб-служба ASP.NET может олицетворять определенного пользователя или любого пользователя, учетные данные которого переданы в текущем запросе. Этот элемент можно использовать для настройки олицетворения в приложениях WCF, работающих в режиме совместимости ASP.NET.

Система конфигурации WCF предоставляет собственный элемент удостоверения для назначения определенного пользователя для олицетворения. Кроме того, клиенты и службы WCF могут быть независимо настроены для олицетворения. Клиенты можно настроить на олицетворение текущего пользователя при передаче запросов.

<behaviors>
     <behavior name="DerivativesCalculatorClientBehavior">
      <clientCredentials>
      <windows allowedImpersonationLevel="Impersonation"/>
      </clientCredentials>
     </behavior>
</behaviors>

Операции службы можно настроить на олицетворение любого пользователя, учетные данные которого переданы в текущем запросе.

[OperationBehavior(Impersonation = ImpersonationOption.Required)]
public void Receive(Message input)

Безопасность: авторизация с использованием списков управления доступом

Для ограничения доступа к ASMX-файлам можно использовать списки управления доступом (ACL). Однако списки управления доступом к файлам WCF .svc игнорируются, за исключением режима совместимости ASP.NET.

Безопасность: авторизация на основе ролей

Режим проверки подлинности Windows, предоставляемый службами IIS, можно использовать в сочетании с предусмотренным в языке конфигурации ASP.NET элементом авторизации для упрощения авторизации на основе ролей для веб-служб ASP.NET, основанных на группах Windows, которым назначены пользователи. В ASP.NET 2.0 появился более общий механизм авторизации на основе ролей: поставщики ролей.

Поставщики ролей - это классы, реализующие базовый интерфейс для отправки запросов о ролях, которым назначен пользователь, причем каждый поставщик ролей предназначен для извлечения этой информации из определенного источника. ASP.NET 2.0 предоставляет поставщик ролей, который может извлекать назначения ролей из базы данных Microsoft SQL Server, и еще один поставщик, способный извлекать назначения ролей из диспетчера авторизации Windows Server 2003.

Механизм поставщика ролей можно использовать независимо от ASP.NET в любом приложении .NET, включая приложение WCF. В следующем примере конфигурации для приложения WCF показано, как использование поставщика ролей ASP.NET является параметром, выбранным с помощью средства ServiceAuthorizationBehavior.

<system.serviceModel>
     <services>
         <service name="Service.ResourceAccessServiceType"
             behaviorConfiguration="ServiceBehavior">
             <endpoint
              address="ResourceAccessService"
              binding="wsHttpBinding"
              contract="Service.IResourceAccessContract"/>
         </service>
     </services>
     <behaviors>
       <behavior name="ServiceBehavior">
       <serviceAuthorization principalPermissionMode="UseAspNetRoles"/>
      </behavior>
     </behaviors>
</system.serviceModel>

Безопасность: авторизация на основе утверждений

Одним из наиболее важных инноваций WCF является его тщательная поддержка авторизации доступа к защищенным ресурсам на основе утверждений. Утверждения состоят из типа, права и значения. В качестве примера можно привести водительское удостоверение: оно содержит ряд утверждений о своем предъявителе, одним из которых является дата рождения предъявителя. Тип этого утверждения - дата рождения, а значение утверждения - дата рождения водителя. Право, которое утверждение дает предъявителю, указывает, что предъявитель может делать со значением утверждения. В случае утверждения даты рождения водителя право состоит во владении: эта дата рождения принадлежит водителю, однако он не может, например, изменять ее. Авторизация на основе утверждений включает в себя авторизацию на основе ролей, поскольку роли являются одним из типов утверждений.

Авторизация на основе утверждений осуществляется путем сравнения набора утверждений с требованиями доступа к операции и предоставления доступа к операции или отказа в доступе к операции в зависимости от результатов этого сравнения. В WCF можно указать класс, используемый для запуска авторизации на основе утверждений, еще раз назначив значение свойству ServiceAuthorizationManagerServiceAuthorizationBehavior.

<behaviors>
     <behavior name='ServiceBehavior'>
     <serviceAuthorization
     serviceAuthorizationManagerType=
                   'Service.AccessChecker, Service' />
     </behavior>
</behaviors>

Классы, используемые для выполнения авторизации на основе утверждений, должны быть производными от класса ServiceAuthorizationManager, в котором имеется только один метод для переопределения - AccessCheck(). WCF вызывает этот метод всякий раз, когда вызывается операция службы и предоставляет OperationContext объект, который имеет утверждения для пользователя в своем ServiceSecurityContext.AuthorizationContext свойстве. WCF выполняет сборку утверждений о пользователе из любого маркера безопасности, предоставленного пользователем для проверки подлинности, что оставляет задачу оценки того, достаточно ли эти утверждения для этой операции.

Этот WCF автоматически собирает утверждения из любого типа маркера безопасности является очень важным инновацией, так как он делает код для авторизации на основе утверждений полностью независимо от механизма проверки подлинности. В противоположность этому авторизация с использованием списков ACL или ролей в ASP.NET тесно связана с проверкой подлинности Windows.

Безопасность: конфиденциальность

Конфиденциальность сообщений, отправляемых и принимаемых веб-службами ASP.NET, может быть обеспечена на уровне транспорта путем настройки приложения в IIS на использование протокола HTTPS. Это можно сделать для приложений WCF, размещенных в службах IIS. Однако приложения WCF, размещенные за пределами IIS, также можно настроить для использования безопасного транспортного протокола. Более важно, приложения WCF также можно настроить для защиты сообщений перед их транспортировкой с помощью протокола WS-Security. Защита только тела сообщения с использованием WS-Security позволяет передавать его с соблюдением конфиденциальности в пункт назначения через посредников.

Глобализация

Язык конфигурации ASP.NET позволяет задавать язык и региональные параметры для отдельных служб. WCF не поддерживает этот параметр конфигурации, кроме ASP.NET режиме совместимости. Чтобы локализовать службу WCF, которая не использует режим совместимости ASP.NET, скомпилируйте тип службы в сборки, зависящие от языка и региональных параметров, и имеют отдельные конечные точки для каждой сборки, относящуюся к языку и региональным параметрам.

См. также