Visual Basic, .NET, ASP, VBScript
 

   
 
Описание для автора не найдено
 
     
   
 
Как работают Web сервисы ASP.NET
Автор: Aaron Skonnard, DevelopMentor
Перевод: Шатохина Надежда(sna@uneta.org), Ukraine .Net Alliance (http://www.uneta.org)
Май 2003
Применяется к:
  • Методы Web сервисов Microsoft® ASP.NET
  • Обмен сообщениями SOAP
  • XML Schema
  • Web сервисы базирующиеся на HTTP
  • Обзор:
    Показано, как методы Web сервисов Microsoft ASP.NET (WebMethods) обеспечивают высокопроизводительный подход к построению Web сервисов. WebMethods могут раскрывать традиционные методы Microsoft .NET, такие как операции Web сервиса, которые поддерживают HTTP, XML, XML Schema, SOAP и WSDL. Обработчик WebMethod (.asmx) автоматически отправляет поступающие SOAP сообщения в соответствующие методы и автоматически сериализует поступающие элементы XML в соответствующие объекты .NET.
    Содерджание:
  • Введение
  • Оболочка WebMethods
  • Диспечеризация сообщений
  • Преобразование XML в объекты
  • Автоматическое генерирование WSDL
  • Заключение
  • Введение

    Сегодня существует два фундаментально различных способа реализации Web сервисов, основанных на HTTP, в Microsoft® .NET. Первой и наиболее низкоуровневой техникой является написание специального класса IHttpHandler, который вставляется в цепочку .NET HTTP pipeline. Этот подход требует использования System.Web API для обработки входящих HTTP сообщений и System.Xml API для обработки конверта SOAP, находящегося в теле HTTP. При написании специального обработчика также требуется создать вручную документ WSDL, который точно описывает вашу реализацию. Чтобы сделать все это правильно, необходимо глубокое понимание спецификаций XML, XSD, SOAP и WSDL, что является для большинства устрашающим условием.

    Более продуктивным способом реализовать Web сервисы является использование WebMethods оболочки Microsoft ASP.NET. С ASP.NET поставляется специальный класс IHttpHandler для .asmx (называемых WebServiceHandler), который обеспечивает набор необходимых вам функциональных возможностей XML, XSD, SOAP и WSDL. И, поскольку WebMethods оболочка защищает вас от сложностей, лежащих в основе XML технологий, вы можете быстро сосредоточиться на существующих проблемах бизнес логики.

    Рисунок 1. Соотношение выгод и потерь между гибкостью и продуктивностью

    Выбор между техниками реализации приводит к общему сравнению выгод и потерь между гибкостью и продуктивностью, как показано на Рисунке 1. Создание специального IHttpHandler дает вам неограниченную гибкость, но также требует большего времени на написание, тестирование и отладку кода. Оболочка WebMethods облегчает организацию вашего Web сервиса и быстроту разработки, но вы явно ограничены рамками оболочки. Однако в случаях, когда оболочка WebMethods не обеспечивает именно того, что вам надо, есть возможность расширить ее, добавляя собственные дополнительные функциональные возможности.

    В общем, пока вы не освоили XML, XSD, SOAP и WSDL и не хотите утруждаться, работая с ними напрямую, лучше продолжайте работать с оболочкой WebMethods. Она поставляет основные сервисы, которые необходимы большинству конечных Web сервисов, а также некоторые интересные возможности расширения, которые позволяют привести оболочку в соответствие вашим конкретным надобностям. Исходя из этого, далее в статье обсуждаются внутренние механизмы работы WebMethods. Если вы новичок в XML Schema и SOAP, перед тем как продолжить прочитайте Understanding XML Schema (http://msdn.microsoft.com/webservices/building/frameworkandstudio/default.aspx?pull=/library/en-us/dnxml/html/understandxsd.asp) и Understanding SOAP (http://msdn.microsoft.com/webservices/building/frameworkandstudio/default.aspx?pull=/library/en-us/dnsoap/html/understandsoap.asp).

    Оболочка WebMethods

    Оболочка WebMethods занимается преобразованиями SOAP сообщений в методы класса .NET. Это делается, прежде всего, путем аннотирования ваших методов атрибутом [WebMethod], находящемся в пространстве имен System.Web.Services. Например, следующий класс .NET содержит четыре метода, два из которых аннотированы атрибутом [WebMethod]:

    using System.Web.Services;
    
    public class MathService
    {
       [WebMethod]
       public double Add(double x, double y) {
          return x + y;
       }
       [WebMethod]
       public double Subtract(double x, double y) {
          return x - y;
       }
       public double Multiply(double x, double y) {
          return x * y;
       }
       public double Divide(double x, double y) {
          return x / y;
       }
    }			
    			

    Чтобы использовать этот класс с оболочкой WebMethods, вам надо компилировать его в сборку и скопировать в виртуальную директорию директории bin. В этом примере методы Add и Subtract затем могут быть раскрыты как операции Web сервиса, в то время как с методами Multiply и Divide этого сделать нельзя (т.к. они не были отмечены атрибутом [WebMethod]).

    Вы раскрываете Add и Subtract как операции Web сервиса через .asmx файл. Чтобы сделать это, создайте новый текстовый файл Math.asmx, содержащий следующее простое описание, и поместите его в ту же виртуальную директорию, которая содержит и сборку (обратите внимание: файл помещается в саму виртуальную директорию, а не в ее дочернюю директорию bin):

    <%@ WebService class="MathService"%>			
    			

    Это описание указывает обработчику .asmx, какой класс использовать для WebMethods, а обработчик чудесным образом заботится обо всем остальном. Например, предположим, виртуальная директория называется 'math' и содержит Math.asmx наряду с тем, что дочерняя директория bin содержит сборку, вызов http://localhost/math/math.asmx приводит к тому, что обработчик .asmx генерирует страницу документации, показанную на Рисунке 2 (см. далее).

    Это один из основных вариантов работы обработчика .asmx. Файл .asmx обычно содержит только описание WebService, которое ссылается на класс Web сервиса по имени (как в примере, показанном ниже). Следовательно, в этом случае, сборка должна уже быть скомпилирована и размещена в директории bin виртуальной директории. Обработчик .asmx также обеспечивает JIT компиляцию исходного кода, находящегося в файле .asmx. Например, следующий файл (названный Mathjit.asmx) содержит описание WebService вместе с исходным кодом класса, на который ссылается.

    <@% WebService class="MathServiceJit" language="C#"%>
    
    using System.Web.Services;
    
    public class MathServiceJit
    {
       [WebMethod]
       public double Add(double x, double y) {
          return x + y;
       }
       [WebMethod]
       public double Subtract(double x, double y) {
          return x - y;
       }
       public double Multiply(double x, double y) {
          return x * y;
       }
       public double Divide(double x, double y) {
          return x / y;
       }
    }			
    			

    Когда к этому файлу доступаются через HTTP впервые, обработчик .asmx компилирует источник и правильно размещает сборку. Обратите внимание, что в описании WebService должен быть также указан и язык программирования, чтобы обработчик .asmx мог выбрать в среде выполнения правильный компилятор. Явным недостатком этого подхода является то, что вы не знаете об ошибках компиляции до тех пор, пока не обратитесь к файлу.

    Рисунок 2. Документация MathService

    При создании нового проекта Web сервиса в Visual Studio® .NET вы всегда используете технику “двух файлов”, когда исходный файл класса отделен от файла .asmx, который на него ссылается. Интегрированная среда разработки (IDE) хорошо скрывает это от вас, но если вы нажмете Show All Files на панели инструментов Solution Explorer, вы увидите в проекте по два файла для каждого класса Web сервиса. Кстати, Visual Studio .NET не поддерживает для файлов .asmx синтаксическое выделение или IntelliSense®, поэтому вы сами решаете, следовать ли в этом направлении. В Web проектах Visual Studio .NET также заботится о создании виртуальной директории и автоматическом компилировании сборки в директорию bin виртуальной директории.

    Перед погружением в детали работы обработчика .asmx давайте коротко обсудим, как обрабатываются сообщения от Internet Information Server (IIS), прежде всего, в обработчике .asmx. Когда входящее HTTP сообщение достигает порта 80, для того, чтобы определить, какая ISAPI DLL должна использоваться для его обработки, IIS использует информацию метабазы IIS. Инсталляция .NET связывает расширения .asmx с Aspnet_isapi.dll, как показано на Рисунке 3.

    Рисунок 3. Связываение IIS и .asmx

    Aspnet_isapi.dll – это стандартное расширение ISAPI, поставляемое .NET Framework, которое просто направляет HTTP запросы в отдельный рабочий процесс, называемый Aspnet_wp.exe. Aspnet_wp.exe выполняет роль хоста для общеязыковой среды выполнения и .NET HTTP pipeline. Как только сообщение входит в .NET HTTP pipeline, pipeline просматривает в файле конфигурации, какой класс IHttpHandler надо использовать для данного расширения. Если вы посмотрите свой файл Machine.config, то увидите, что он содержит httpHandler, связанный с расширением .asmx, как показано здесь:

    <configuration>
      <system.web>
        <httpHandlers>  
            <add verb="*" path="*.asmx" type="System.Web.Services.Protocols.WebServiceHandlerFactory, 
    System.Web.Services, Version=1.0.3300.0, Culture=neutral, 
    PublicKeyToken=b03f5f7f11d50a3a" validate="false"/>
    ...			
    			

    Итак, когда сообщение поступает в .NET HTTP pipeline, нацеливаясь на файл .asmx, pipeline заходит в класс WebServiceHandlerFactory, чтобы создать новый объект WebServiceHandler, который может использоваться для обработки запроса (с помощью метода IHttpHandlerProcessRequest). Затем объект WebServiceHandler открывает физический файл .asmx, чтобы определить имя класса, содержащего ваш WebMethods. Более подробная информация о работе .NET HTTP pipeline представлена в HTTP Pipelines: Securely Implement Request Processing, Filtering, and Content Redirection with HTTP Pipelines in ASP.NET (http://msdn.microsoft.com/library/default.asp?url=/msdnmag/issues/02/09/HTTPPipelines/default.aspx).

    Сразу после того, как .NET HTTP pipeline вызывает обработчик .asmx, чудесным образом начинается обработка XML, XSD, SOAP и WSDL. Остальные функциональные возможности, предоставляемые обработчиком .asmx, могут быть разделены на три основные группы: 1) координирование сообщений, 2) преобразование XML в объекты и 3) автоматическое генерирование WSDL и документации. Давайте каждую из этих групп рассмотрим более детально.

    Диспечеризация сообщений

    Когда HTTP pipeline вызывает обработчик .asmx, просматривая описание WebService в файле .asmx, он определяет, какой класс .NET использовать. Затем он просматривает поступившее HTTP сообщение, чтобы определить, какой именно метод вызывать в данном классе. Чтобы вызвать операцию Add, показанную в предыдущих примерах, входящее HTTP сообщение должно выглядеть примерно так:

    POST /math/math.asmx HTTP/1.1
    Host: localhost
    Content-Type: text/xml; charset=utf-8
    Content-Length: length
    SOAPAction: "http://tempuri.org/Add"
    
    <soap:Envelope 
      xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
    >
      <soap:Body>
        <Add xmlns="http://tempuri.org/">
          <x>33</x>
          <y>66</y>
        </Add>
      </soap:Body>
    </soap:Envelope>			
    			

    На самом деле во входящем HTTP сообщении есть два участка, которые могут использоваться для определения метода, который должен быть вызван в классе: заголовок SOAPAction или имя запрашиваемого элемента (т.е. имя элемента в пределах элемента soap:Body). В этом случае хотя бы один из них определяет имя метода, который хочет вызвать отправитель.

    Для диспечеризации сообщения обработчик .asmx по умолчанию использует заголовок SOAPAction. Значит, обработчик .asmx смотрит на заголовок SOAPAction в сообщении, а затем, используя .NET рефлексию, проверяет методы класса. Он рассматривает только методы, помеченные атрибутом [WebMethod], но, просматривая значение SOAPAction каждого метода, он точно определяет, какой метод вызывать. Поскольку мы явно не определили значение SOAPAction в методах нашего класса, обработчик .asmx принимает, что значением SOAPAction будет сочетание пространства имен Web сервиса и имени метода. Поскольку мы также не определили и пространство имен, обработчик по умолчанию присваивает http://tempuri.org. Таким образом, значение по умолчанию SOAPAction для метода Add будет http://tempuri.org/Add.

    Вы можете изменить пространство имен Web сервиса, помечая класс атрибутом [WebService], так же как и точное значение SOAPAction, помечая WebMethods атрибутом [SoapDocumentMethod], как показано далее:

    using System.Web.Services;
    using System.Web.Services.Protocols;
    
    [WebService(Namespace="http://example.org/math")]
    public class MathService
    {
       [WebMethod]
       public double Add(double x, double y) {
          return x + y;
       }
       [WebMethod]
       [SoapDocumentMethod(Action="urn:math:subtract")]
       public double Subtract(double x, double y) {
          return x - y;
       }
       ...
    }			
    			

    Теперь обработчик .asmx ожидает, что значение SOAPAction для метода Add будет http://example.org/math/Add и urn:math:subtract для метода Subtract (поскольку мы явно задали это значение). Например, следующее сообщение HTTP запроса вызывает операцию Subtract:

    POST /math/math.asmx HTTP/1.1
    Host: localhost
    Content-Type: text/xml; charset=utf-8
    Content-Length: length
    SOAPAction: "urn:math:subtract"
    
    <soap:Envelope 
      xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
    >
      <soap:Body>
        <Subtract xmlns="http://example.org/math">
          <x>33</x>
          <y>66</y>
        </Subtract>
      </soap:Body>
    </soap:Envelope>			
    			

    Если обработчик .asmx не находит SOAPAction, подходящего для входящего HTTP сообщения, он просто формирует исключительную ситуацию (позже рассмотрим, как обрабатываются исключительные ситуации). Если для диспечерезации метода вы не используете заголовок SOAPAction, помечая класс свойством RoutingStyle атрибута [SoapDocumentService], вы можете указать обработчику .asmx использовать имя элемента запроса. Если вы делаете это, то также надо указать, что WebMethods не нуждаются в значении SOAPAction, путем установления их значений в пустую строку, как показано ниже:

    using System.Web.Services;
    using System.Web.Services.Protocols;
    
    [WebService(Namespace="http://example.org/math")]
    [SoapDocumentService(
      RoutingStyle=SoapServiceRoutingStyle.RequestElement)]
    public class MathService
    {
       [WebMethod]
       [SoapDocumentMethod(Action="")]
       public double Add(double x, double y) {
          return x + y;
       }
       [WebMethod]
       [SoapDocumentMethod(Action="")]
       public double Subtract(double x, double y) {
          return x - y;
       }
        ...
    }			
    			

    В этом случае обработчик даже не рассматривает значение SOAPAction – он использует вместо него имя элемента запроса. Например, ожидается ,что имя элемента запроса для метода Add будет Add (из пространства имен http://example.org/math), как показано в этом сообщении HTTP запроса:

    POST /math/math.asmx HTTP/1.1
    Host: localhost
    Content-Type: text/xml; charset=utf-8
    Content-Length: length
    SOAPAction: ""
    
    <soap:Envelope 
      xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
    >
      <soap:Body>
        <Add xmlns="http://example.org/math">
          <x>33</x>
          <y>66</y>
        </Add>
      </soap:Body>
    </soap:Envelope>			
    			

    Значит, первое, что делает обработчик .asmx при получении входящего HTTP сообщения, – он определяет, как перенаправить сообщение в соответствующий WebMethod. Однако до того как он действительно сможет вызвать метод, он должен преобразовать входящий XML в .NET объекты.

    Преобразование XML в объекты

    Как только обработчик WebMehod определил, какой метод надо вызвать, он должен десериализовать XML сообщение в .NET объекты, которые могут быть предоставлены во время вызова метода. Так же как и при диспечеризации сообщения, обработчик проверяет класс с помощью рефлексии, чтобы выяснить, как обрабатывать входящее XML сообщение. Класс XmlSerializer осуществляет автоматическое преобразование между XML и объектами в пространстве имен System.Xml.Serialization.

    XmlSerializer делает возможным преобразование любого public типа .NET в тип XML Schema и, вместе с тем, может проводить автоматические преобразования между .NET объектами и документами XML (см. Рисунок 4). XmlSerializer ограничен теми возможностями, которые сегодня поддерживает XML Schema, поэтому он не может работать со всеми сложностями сегодняшних объектных моделей, такими как комплексные не древовидные диаграммы объектов, дублирующие указатели и т.д. Несмотря на это, XmlSerializer может работать с большинством комплексных типов, используемых разработчиками.

    Для приведенного выше примера Add XmlSerializer преобразует элементы x и y в .NET double значение, которые затем смогут предоставляться при вызове Add. Метод Add возвращает вызывающему значение типа double, которое затем должно быть опять сериализовано в XML элемент в рамках SOAP ответа.

    Рисунок 4. Преобразование XML в объекты

    Также XmlSerializer может автоматически работать с комплексными типами (за исключением описанных выше ограничений). Например, следующий WebMethod вычисляет расстояние между двумя структурами Point:

    using System;
    using System.Web.Services;
    
    public class Point {
      public double x; 
      public double y;
    }
    [WebService(Namespace="urn:geometry")]
    public class Geometry {
      [WebMethod]
      public double Distance(Point orig, Point dest) {
        return Math.Sqrt(Math.Pow(orig.x-dest.x, 2) +
                         Math.Pow(orig.y-dest.y, 2));
      }
    }			
    			

    SOAP сообщение запроса для этой операции будет содержать элемент Distance, который включает два дочерних элемента, orig и dest, и каждый из этих элементов должен содержать дочерние x и y элементы:

    <soap:Envelope 
      xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
    >
      <soap:Body>
        <Distance xmlns="urn:geometry">
          <orig>
            <x>0</x>
            <y>0</y>
          </orig>
          <dest>
            <x>3</x>
            <y>4</y>
          </dest>
        </Distance>
      </soap:Body>
    </soap:Envelope>			
    			

    В этом случае SOAP сообщение ответа будет содержать элемент DistanceResponse, включающий элемент DistanceResult типа double:

    <soap:Envelope 
      xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
    >
      <soap:Body>
        <DistanceResponse 
          xmlns="urn:geometry">
          <DistanceResult>5</DistanceResult> 
        </DistanceResponse>
      </soap:Body>
    </soap:Envelope>			
    			

    Применяемое по умолчанию XML преобразование использует имя метода в качестве имени элемента запроса и имена параметров в качестве имен дочерних элементов. Структура каждого параметра зависит от структуры типа. Имена public полей и свойств просто преобразовываются в дочерние элементы, как в случае x и y (в Point). Именем элемента ответа по умолчанию становится имя элемента запроса, оканчивающееся словом "Response". Элемент ответа также содержит дочерние элементы, названные так же как и элементы запроса, только оканчивающиеся словом "Result".

    Есть возможность освободиться от стандартного XML преобразования путем использования большого количества встроенных атрибутов преобразования. Например, для преобразования имени типа и пространства имен можно использовать атрибут [XmlType]. Чтобы контролировать то, как параметры или члены класса преобразовывают элементы или атрибуты, вы можете пользоваться атрибутами [XmlElement] и [XmlAttribute], соответственно. А для контроля за тем, как сам метод преобразовывается в имена элементов в сообщениях запроса/ответа, можно воспользоваться атрибутом [SoapDocumentMethod]. Например, ознакомьтесь со следующей версией Distance, в которой используются различные атрибуты:

    using System;
    using System.Web.Services;
    using System.Web.Services.Protocols;
    using System.Xml.Serialization;
    
    public class Point {
      [XmlAttribute]
      public double x;
      [XmlAttribute] 
      public double y;
    }
    [WebService(Namespace="urn:geometry")]
    public class Geometry {
      [WebMethod]
      [SoapDocumentMethod(RequestElementName="CalcDistance",
         ResponseElementName="CalculatedDistance")]
      [return: XmlElement("result")]
      public double Distance(
        [XmlElement("o")]Point orig, [XmlElement("d")]Point dest) {
        return Math.Sqrt(Math.Pow(orig.x-dest.x, 2) +
                         Math.Pow(orig.y-dest.y, 2));
      }
    }			
    			

    В этой версии Distance ожидается, что входящее SOAP сообщение будет выглядеть следующим образом:

    <soap:Envelope 
      xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
    >
      <soap:Body>
        <CalcDistance xmlns="urn:geometry">
          <o x="0" y="0" />
          <d x="3" y="4" />
        </CalcDistance>
      </soap:Body>
    </soap:Envelope>			
    			

    И будет сгенерировано такое SOAP сообщение ответа:

    <soap:Envelope 
      xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
    >
      <soap:Body>
        <CalculatedDistance xmlns="urn:geometry">
          <result>5</result>
        </CalculatedDistance>
      </soap:Body>
    </soap:Envelope>			
    			

    Для реализации и определения приведенного выше преобразования, применяемого по умолчанию, обработчик .asmx использует документ/литерал стиль SOAP. Это означает, что описание WSDL будет содержать буквенные определения XML schema, описывающие и элементы запроса, и элементы ответа, используемые в SOAP сообщениях (т.е. правила SOAP кодирования не используются).

    Обработчик .asmx также делает возможным использование rpc/литерал стиля SOAP. Это означает, что SOAP Body содержит XML представление вызова RPC и параметры сериализовываются с использованием правил SOAP кодирования (т.е. XML Schema не нужна). Соответственно, вместо атрибутов [SoapDocumentService] и [SoapDocumentMethod] вы используете [SoapRpcService] и [SoapRpcMethod]. Более подробно о различиях в этих стилях см. в разделе MSDN Understanding SOAP (http://msdn.microsoft.com/webservices/building/frameworkandstudio/default.aspx?pull=/library/en-us/dnsoap/html/understandsoap.asp).

    Как видите, есть возможность полностью изменить процесс преобразования данного метода в SOAP сообщение. XmlSerializer обеспечивает мощный механизм сериализации со многими возможностями, о которых у нас нет времени здесь говорить. Более подробно о том, как работает XmlSerializer, см. в разделе MSDN Moving to .NET and Web Services (http://msdn.microsoft.com/library/default.asp?url=/msdnmag/issues/01/11/webserv/). Я также рассмотрел многие нюансы XmlSerializer, не раскрытые в моей ежемесячной колонке MSDN Magazine, XML Files (http://msdn.microsoft.com/msdnmag/find/default.aspx?type=Ti&phrase=XML%20Files) (смотрите список колонок в online архивах).

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

    Если, все-таки, вы хотите использовать информацию заголовка из WebMethod, вы должны предоставить класс .NET, наследуемый от SoapHeader, который представляет XML Schema заголовков (следуя рекомендациям преобразования, приведенным выше). Затем вы определяете переменную члена этого типа, выполняющую роль «заполнителя» для экземпляров заголовка. И наконец, вы помечаете каждый WebMethod, нуждающийся в доступе к заголовку, определяя имя того поля, куда вы хотите его направить.

    Например, SOAP запрос, содержащий заголовок UsernameToken с целью аутентификации:

    <soap:Envelope 
      xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
    >
      <soap:Header>
        <x:UsernameToken xmlns:x="http://example.org/security">
          <username>Mary</username>
          <password>yraM</password>
        </x:UsernameToken>
      </soap:Header>
      <soap:Body>
        <CalcDistance xmlns="urn:geometry">
           ...			
    			

    Чтобы сделать возможной для обработчика .asmx десериализацию заголовка, сначала надо определить класс .NET, представляющий предполагаемый тип XML Schema (обратите внимание: если у вас на самом деле есть XML Schema для заголовка, вы можете генерировать класс, используя xsd.exe /c). В этом случае соответствующий класс выглядит следующим образом:

    [XmlType(Namespace="http://example.org/security")]
    [XmlRoot(Namespace="http://example.org/security")]
    public class UsernameToken : SoapHeader {
       public string username;
       public string password;
    }			
    			

    Затем просто надо определить переменную члена в вашем классе WebMethod, чтобы хранить экземпляр класса заголовка , и аннотировать WebMethods атрибутом [SoapHeader], как показано ниже:

    using System;
    using System.Web.Services;
    using System.Web.Services.Protocols;
    
     [WebService(Namespace="urn:geometry")]
    public class Geometry {
    
      public UsernameToken Token;
    
      [WebMethod]
      [SoapHeader("Token")]
      public double Distance(Point orig, Point dest) {
    
        if (!Token.username.Equals(Reverse(Token.password)))
           throw new Exception("access denied");
    
        return Math.Sqrt(Math.Pow(orig.x-dest.x, 2) +
                         Math.Pow(orig.y-dest.y, 2));
      }
    }			
    			

    Затем в WebMethod вы можете обратиться к полю Token и извлечь информацию, которая была предоставлена заголовком. Вы также можете отправить заголовки обратно клиенту, используя ту же технику – вам просто надо определить направление заголовка в описании атрибута [SoapHeader]. Более подробную информацию об обработке SOAP заголовков в оболочке WebMethods см. в разделе MSDN Digging into SOAP Headers with the .NET Framework. (http://msdn.microsoft.com/webservices/building/frameworkandstudio/default.aspx?pull=/library/en-us/dnservice/html/service06182002.asp)

    Обработчик .asmx также обеспечивает автоматическую сериализацию исключительных ситуаций .NET. Любая необработанная исключительная ситуация,перехваченная обработчиком .asmx, автоматически сериализуется в элемент SOAP Fault в ответе. Например, в предыдущем примере, если имя пользователя не совпадает с паролем, наш код формирует исключительную ситуацию .NET. Тогда обработчик .asmx обработает ее и сериализует в SOAP ответ, как показано ниже:

    <soap:Envelope 
      xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
    >
      <soap:Body>
        <soap:Fault>
          <faultcode>soap:Server</faultcode>    
          <faultstring>Server was unable to process request. --&gt; access denied</faultstring>
          <detail />
        </soap:Fault>
      </soap:Body>
    </soap:Envelope>			
    			

    Если вы хотите еще больше контролировать элемент SOAP Fault, вы можете также явно сформировать объект SoapException, определяя все детали элемента SOAP Fault, такие как элементы faultcode, faulstring, faultactor и detail. Более подробная информации представлена в разделе MSDN Using SOAP Faults (http://msdn.microsoft.com/webservices/building/frameworkandstudio/default.aspx?pull=/library/en-us/dnservice/html/service09172002.asp).

    Как видите, чтобы понять, как работает WebMethods, необходимо еще разобраться с механизмом, лежащим в основе сериализации, и всем многообразием его возможностей. Преимуществом механизма сериализации является то, что он скрывает весь лежащий в основе XML API код, который обычно вам приходится писать в специальном обработчике. Однако, в то время как большинство разработчиков считают это положительным моментом, некоторые называют это недостатком, потому что все еще хотят самостоятельно работать с SOAP сообщением в пределах реализации WebMethod. Более детально о том, как использовать такой смешанный подход, см. в разделе MSDN Accessing Raw SOAP Messages in ASP.NET Web Services (http://msdn.microsoft.com/library/default.asp?url=/msdnmag/issues/03/03/WebServices/default.aspx).

    Автоматическое генерирование WSDL

    Клиентам надо точно знать, как должно выглядеть SOAP сообщение, чтобы успешно работать с ним. Общепринятым является предоставлять описания Web сервиса через WSDL (и встроенные XSD определения). Для этого обработчик .asmx автоматически генерирует и страницу документации, и описание WSDL, которое точно отражает интерфейс WebMethod. Если вы применили группу атрибутов преобразования к вашим WebMethods, все они будут отражены в сгенерированной документации.

    Если вы посмотрите файл .asmx, то найдете страницу документации, такую как показано на Рисунке 2. Эта страница документации генерируется страницей .aspx, называемой DefaultWsdlHelpGenerator.aspx (находящейся в C:\windows\Microsoft.NET\Framework\ v1.0.3705\config). Если откроете файл, вы увидите, что это всего лишь стандартная страница ASP.NET, которая использует .NET рефлексию для генерирования документации. Эта возможность позволяет документации всегда соответствовать коду. Просто модифицируя этот файл, вы можете изменять генерируемую документацию.

    Также можно блокировать генерирование документации на основе виртуальной директории, определяя другой файл документации в файле Web.config:

    <configuration>
      <system.web>
        <webServices>
          <wsdlHelpGenerator href="MyDocumentation.aspx"/>
        </webServices>
        ...			
    			

    Если клиент завершает запрос GET для .asmx символами "?wsdl" в строке запроса, обработчик .asmx вместо документации генерирует описание WSDL. Клиенты могут использовать описание WSDL для генерирования proxy классов, которые автоматически знают, как общаться с Web сервисом (т.е. используя Wsdl.exe в .NET).

    Чтобы изменить процесс генерирования WSDL, вы можете написать класс SoapExtensionReflector и зарегистрировать его с оболочкой WebMethods в файле Web.config. Затем, когда обработчик .asmx будет генерировать описание WSDL, он вызовет ваш класс и даст вам возможность изменить окончательное описание, поставляемое клиенту. Более подробно о том, как писать классы SoapExtensionReflector, см. в разделе MSDN SoapExtensionReflectors in ASP.NET Web Services (http://msdn.microsoft.com/msdntv/episode.aspx?xml=episodes/en/20030320WebServicesMP/manifest.xml).

    Используя две различные техники, вы можете полностью блокировать процесс генерирования WSDL. Во-первых, для доступа клиентами вы можете предоставить статический WSDL документ в вашей виртуальной директории и затем блокировать генератор документации, удалив его из вашего файла Web.config, как показано ниже:

    <configuration>
      <system.web>
        <webServices>
          <protocols>
            <remove name="Documentation"/>
          </protocols>
          ...			
    			

    Немного более автоматизированной техникой является использование атрибута [WebServicesBinding] для определения местоположения статического документа WSDL в виртуальной директории, которую реализовывает класс WebMethod. Вы также должны определить имя WSDL binding, которое реализовывает каждый WebMethod, используя атрибут [SoapDocumentMethod]. Процесс автоматического генерирования WSDL импортирует ваш статический WSDL файл и «завернет» его в новое описание сервиса. Более подробная информация по этой технике представлена в статье MSDN Place XML Message Design Ahead of Schema Planning to Improve Web Service Interoperability (http://msdn.microsoft.com/library/default.asp?url=/msdnmag/issues/02/12/WebServicesDesign/).

    Сегодня очень тяжело вручную создавать WSDL, потому что до сих пор нет достаточного количества доступных редакторов WSDL. Поэтому автоматическое генерирование документации/ WSDL является ценной частью оболочки WebMethods, которая облегчит жизнь многим разработчикам.

    Заключение

    Оболочка WebMethods ASP.NET обеспечивает высокопроизводительный подход к построению Web сервисов. WebMethods сделали возможным использовать традиционные методы .NET в качестве операций Web сервиса, которые поддерживают HTTP, XML, XML Schema, SOAP и WSDL. Обработчик WebMethod (.asmx) автоматически определяет, как отправить входящие SOAP сообщения в соответствующий метод, в какой точке он автоматически сериализует входящие XML элементы в соответствующие объекты .NET. И упрощая жизнь клиента, обработчик .asmx также обеспечивает автоматическую поддержку для генерирования документации для человека (HTML) и для машины (WSDL).

    Хотя по сравнению со специальным IHttpHandlers оболочка WebMethods может выглядеть несколько ограниченной, она обеспечивает мощную модель расширяемости, известную как оболочка SOAP расширения. Расширения SOAP обеспечивают возможность для удовлетворения ваших конкретных нужд ввести дополнительные функциональные возможности, помимо обсуждаемых здесь. Например, Microsoft выпустила Web Services Enhancements 1.0 для Microsoft .NET (WSE), которые просто предоставляют класс SoapExtension, вводящий в оболочку WebMethods поддержку для нескольких GXA спецификаций. Более подробная информация по написанию SOAP расширений представлена в MSDN Fun with SOAP Extensions (http://msdn.microsoft.com/webservices/building/frameworkandstudio/default.aspx?pull=/library/en-us/dnaspnet/html/asp03222001.asp).

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

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

       
       
         
      VBNet рекомендует