Служба WCF 4 с конечными точками REST / SOAP в IIS 7.5

#c# #wcf #rest #soap

#c# #wcf #rest #soap

Вопрос:

Здравствуйте и спасибо за чтение.

Я пытаюсь создать службу, размещенную в IIS 7.5, для которой доступно несколько конечных точек.

У меня такое чувство, что проблема кроется в моем web.config, но я опубликую здесь свой код службы. Файла интерфейса нет, поскольку я использую более новые функции WCF 4, файла .svc также нет.

Насколько я понимаю, вся маршрутизация обрабатывается в Global.asax.cs с использованием функции RouteTable.

Независимо от того, в коде / конфигурации —

 [ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
// NOTE: If the service is renamed, remember to update the global.asax.cs file
public class Service1
{
    // TODO: Implement the collection resource that will contain the SampleItem instances

    [WebGet(UriTemplate = "HelloWorld")]
    public string HelloWorld()
    {
        // TODO: Replace the current implementation to return a collection of SampleItem instances
        return "Hello World!";
    }
}
  

И теперь, конфигурация с изменениями, которые, как я думал, потребуется внести (я не уверен, нужно ли мне сохранять блок standardEndpoints, но с ним или без него я все еще получаю сообщения об ошибках. —

 <services>
  <service name="AiSynthDocSvc.Service1" behaviorConfiguration="HttpGetMetadata">
    <endpoint name="rest"
              address=""
              binding="webHttpBinding"
              contract="AiSynthDocSvc.Service1"
              behaviorConfiguration="REST" />
    <endpoint name="soap"
              address="soap"
              binding="basicHttpBinding"
              contract="AiSynthDocSvc.Service1" />
    <endpoint name="mex"
              address="mex"
              binding="mexHttpBinding"
              contract="IMetadataExchange" />
  </service>
</services>    

<behaviors>
  <endpointBehaviors>
    <behavior name="REST">
      <webHttp/>
    </behavior>
  </endpointBehaviors>
  <serviceBehaviors>
    <behavior name="HttpGetMetadata">
      <serviceMetadata httpGetEnabled="true" />
    </behavior>
  </serviceBehaviors>
</behaviors>

<standardEndpoints>
  <webHttpEndpoint>
    <!-- 
        Configure the WCF REST service base address via the global.asax.cs file and the default endpoint 
        via the attributes on the <standardEndpoint> element below
    -->
    <standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true"/>
  </webHttpEndpoint>
</standardEndpoints>
  

Глобальный файл.asax.cs был оставлен в покое.

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

Конечная точка в » не имеет привязки к None MessageVersion. ‘Система.ServiceModel.Описание.WebHttpBehavior’ предназначен только для использования с webHttpBinding или аналогичными привязками.

У кого-нибудь есть идеи по этому поводу?

Спасибо,

Захари Картер

Комментарии:

1. Какой URL вы используете для доступа к своей службе??

2. Также: вы говорите, что у вас нет файла *.svc — как тогда активируется ваша служба? Либо вам нужен файл *.svc, либо вам нужен тег <serviceActivations> в вашей конфигурации <serviceHostingEnvironment>.

3. Служба развернута на веб-сайте по умолчанию на порту 80, поэтому для доступа к ней достаточно — localhost / WebApp /ServiceName . Кроме того, возможность создавать службы без файла .svc является новой функцией в .NET 4.0. Вместо обращения к файлу svc был добавлен новый класс для корректной маршрутизации запроса к соответствующей службе.

4. Можете ли вы показать нам , как вы добавили службу в таблицу маршрутов?? Это, скорее всего, было бы в global.asax.cs — который, как вы сказали, вы не трогали — так что это заставляет меня задуматься……

5. Конечно — private void RegisterRoutes() { // Отредактируйте базовый адрес Service1, заменив строку «Service1» под таблицей маршрутизации. Маршруты. Добавить(новый ServiceRoute(«Service1», новый WebServiceHostFactory(), typeof(Service1))); }

Ответ №1:

Хорошо, я попытался скопировать ваш материал — для меня работает как шарм 🙂

  • Я использовал ваш класс обслуживания — никаких изменений
  • Я использовал ваш RegisterRoutes вызов в global.asax.cs

Когда я запускаю веб-приложение из Visual Studio, у меня появляется Cassini (встроенный веб-сервер) http://localhost:3131/ — в вашем случае это может настораживать.

Теперь я могу легко перемещаться туда с помощью второго окна браузера, и я получаю простой ответ на этот URL:

 http://localhost:3131/Service1/HelloWorld
 --------------------  
 from Cassini
                      -------- 
                   name (first param) in ServiceRoute registration
                               ----------- 
                               from your URI template on the WebGet attribute
  

Работает ли для вас тот же URL-адрес??

Обновление: вот моя конфигурация — я могу подключиться к http://localhost:3131/Service1/HelloWorld в браузере с помощью REST, и я могу подключиться к http://localhost:3131/Service1/soap тестовому клиенту WCF для выполнения вызова SOAP (моя Service1 жизнь находится в RestWebApp пространстве имен — таким образом, мои имена служб и контрактов немного отличаются от ваших — но в остальном, я полагаю, что это идентично вашей собственной конфигурации):

   <system.serviceModel>
    <serviceHostingEnvironment     
        aspNetCompatibilityEnabled="true" />
    <services>
      <service name="RestWebApp.Service1" behaviorConfiguration="Meta">
        <endpoint name="rest" 
                  address=""
                  binding="webHttpBinding"
                  contract="RestWebApp.Service1"
                  behaviorConfiguration="REST" />
        <endpoint name="SOAP"
            address="soap"
            binding="basicHttpBinding"
            contract="RestWebApp.Service1" />
        <endpoint name="mex"
            address="mex"
            binding="mexHttpBinding"
            contract="IMetadataExchange" />
      </service>
    </services>
    <behaviors>
      <endpointBehaviors>
        <behavior name="REST">
          <webHttp/>
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="Meta">
          <serviceMetadata httpGetEnabled="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <standardEndpoints>
      <webHttpEndpoint>
        <!-- 
        Configure the WCF REST service base address via the global.asax.cs file and the default endpoint 
        via the attributes on the <standardEndpoint> element below
        -->
        <standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true"/>
      </webHttpEndpoint>
    </standardEndpoints>
  </system.serviceModel>
  

Комментарии:

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

2. Моя конечная точка soap выглядит как — <имя конечной точки = «soap» адрес = «soap» привязка =»BasicHttpBinding» контракт =»AiSynthDocSvc.Service1″ /> Но переход к localhost: 80 / Service1 /soap выдает следующее сообщение об ошибке — Конечная точка в ‘ vm-scctest.amcad.com/AiSynthDocSvc/Service1/soap ‘ не имеет привязки к None MessageVersion. ‘Система. ServiceModel. Описание. WebHttpBehavior’ предназначен только для использования с webHttpBinding или аналогичными привязками.

3. Опять же, я думаю, что это связано с тем, что для конфигурации поведения службы установлено значение webHttpBinding, а для конфигурации поведения конечной точки — значение BasicHttpBinding.

4. @Zachary Carter: Я так не думаю — вы присвоили своему поведению конечной точки (которое имеет webHttp значение) имя, поэтому его следует использовать, только если вы действительно определяете его в теге <endpoint> . Или вы на самом деле не публиковали свою реальную конфигурацию?? Есть ли у вас поведение конечной точки по умолчанию (без имени), которое применяется ко всем конечным точкам??

5. Я думаю, что я включил это. Я думаю, что это может быть причиной проблемы — <serviceBehaviors> <имя поведения=»HttpGetMetadata»> <serviceMetadata httpGetEnabled=»true» /> </поведение> </serviceBehaviors> <имя службы =»AiSynthDocSvc.Service1″ behaviorConfiguration =»HttpGetMetadata»>

Ответ №2:

Спасибо за это, это мне очень помогло.

Проблема в моем случае заключалась в том, что у меня было настроено поведение по умолчанию, которое содержит webHttp. После присвоения ему name = «REST» и настройки моей конечной точки webHttpBinding behaviourConfiguration =»REST» У меня больше не было ошибок.

 <system.serviceModel>
<bindings>
  <customBinding>
    <binding name="CustomBinding_IMobileService">
      <binaryMessageEncoding />
      <httpTransport />
    </binding>
  </customBinding>
</bindings>
<client>
  <endpoint address="http://localhost:6862/silverlight/services/MobileService.svc"
    binding="customBinding" bindingConfiguration="CustomBinding_IMobileService"
    contract="AlchemyMobileService.IMobileService" name="CustomBinding_IMobileService" />
</client>
<services>
  <service name="MobileService.Alchemy">
    <endpoint address="http://localhost:8732/mobileservice" binding="webHttpBinding" contract="MobileService.IAlchemy" behaviorConfiguration="REST">
    </endpoint>
  </service>
</services>
<behaviors>
  <serviceBehaviors>
    <behavior>
      <serviceDebug includeExceptionDetailInFaults="True" />
    </behavior>
  </serviceBehaviors>
  <endpointBehaviors>
    <behavior name="REST">
      <webHttp />
    </behavior>
  </endpointBehaviors>
</behaviors>