Ошибка WCF: метод 405 запрещен

Схожу с ума с этим вопросом. У меня есть решение с двумя проектами, один из них - простой старый html с вызовом jquery ajax, а другой - сервис WCF. Страница html вызовет ajax-вызов службы WCF, чтобы получить строку json и использовать ее для отображения.

Теперь проблема в том, что всякий раз, когда я запускаю в режиме отладки, и html-страница, и WCF будут запускаться с другим портом. И это создало для меня проблему с перекрестным происхождением, когда я выполняю тестирование (т.е. получаю ошибку 405 Method Not Allowed с типом вызова = OPTIONS в Firefox). Я бы трижды проверил метод вызова в моем сценарии ajax, и служба WCF такая же (GET).

Я поискал в Google, но обнаружил, что либо мне нужно установить расширение, либо выполнить некоторую настройку в IIS, что я нашел громоздким, поскольку то, что я делаю, является чем-то простым. Следуя одному примеру, я бы добавил следующую конфигурацию в свой web.config, но это не сработало:

    <system.serviceModel>
    <bindings>
      <webHttpBinding>
        <binding name="crossDomain" crossDomainScriptAccessEnabled="true" />
      </webHttpBinding>
    </bindings>
    <behaviors>
      <endpointBehaviors>
        <behavior name="MobileService.webHttpBehavior">
          <webHttp />
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="MyServiceBehavior">
          <serviceMetadata httpGetEnabled="true"  />
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
    <services>
      <service name="MobileService.SimpleMemberInfo" behaviorConfiguration="MyServiceBehavior">
        <endpoint address="" binding="webHttpBinding" contract="MobileService.IMemberInfo" bindingConfiguration="crossDomain" behaviorConfiguration="MobileService.webHttpBehavior">
        </endpoint>
      </service>
    </services>
  </system.serviceModel>
  <system.webServer>
    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
        <add name="Access-Control-Allow-Methods" value="GET" />
        <add name="Access-Control-Allow-Headers" value="Content-Type, Accept" />
      </customHeaders>
    </httpProtocol>
    <modules runAllManagedModulesForAllRequests="true"/>
    <directoryBrowse enabled="true"/>
    </system.webServer>

У кого-нибудь есть идея избавиться от этой досадной проблемы?

РЕДАКТИРОВАТЬ: Чтобы добавить, я запускаю отладку с помощью IIS Express, который поставляется вместе с VS Studio 2012.

Добавить код WCF и обновить файл web.config

[ServiceContract]
public interface IMemberInfo
{
    [WebInvoke(Method = "GET",
           BodyStyle = WebMessageBodyStyle.Wrapped,
           ResponseFormat = WebMessageFormat.Json
    )]
    [OperationContract]
    string GetMemberInfoById();
    // TODO: Add your service operations here
}

Мой сценарий:

$(document).ready(function () {
    $.ajax("http://localhost:32972/SimpleMemberInfo.svc/GetMemberInfoById", {
        cache: false,
        beforeSend: function (xhr) {
            $.mobile.showPageLoadingMsg();
        },
        complete: function () {
            $.mobile.hidePageLoadingMsg();
        },
        contentType: 'application/json',
        dataType: 'json',
        type: 'GET',
        error: function () {
            alert('Something awful happened');
        },
        success: function (data) {
            var s = "";

            s += "<li>" + data + "</li>";
            $("#myList").html(s);

        }
    });
});

person ipohfly    schedule 05.11.2012    source источник
comment
Эта ссылка может помочь stackoverflow.com / questions / 2202500 /   -  person Mihai    schedule 05.11.2012
comment
Спасибо. Я пробовал, но ничего не вышло.   -  person ipohfly    schedule 05.11.2012
comment
ops ok ... но если ни один из ответов не помог, мне следует выбрать ближайший?   -  person ipohfly    schedule 06.11.2012
comment
Я отредактировал ваше название. См. Должны ли вопросы включать «теги» в свои заголовки?, где нет единого мнения, не следует.   -  person John Saunders    schedule 06.11.2012


Ответы (5)


Вам необходимо использовать JSONP для междоменного вызова, чтобы обойти ограничения браузера, и обновить свой web.config, установив для crossDomainScriptAccessEnabled значение true, чтобы обойти серверные. В ответе есть хороший пример: как избежать междоменной политики в jquery ajax для использования службы wcf?

У вас также может быть проблема с запросами GET. Попробуйте исправления, описанные здесь: Заставить веб-службу WCF работать с GET запросы

В целом вам нужен web.config, который выглядит примерно так:

<bindings>
  <webHttpBinding>
    <binding name="crossDomain" crossDomainScriptAccessEnabled="true" />
  </webHttpBinding>
</bindings>
<behaviors>
  <endpointBehavior>
    <behavior name="restBehavior">
      <webHttp />
    </behavior>
  </endpointBehavior>
  <serviceBehavior>         
     <behavior name="MyServiceBehavior">
        <serviceMetadata httpGetEnabled="true"  />
        <serviceDebug includeExceptionDetailInFaults="true"/>
     </behavior>
  </serviceBehavior>
</behaviors>
<services>
  <service name="..." behaviorConfiguration="MyServiceBehavior">
    <endpoint address="" binding="webHttpBinding" bindingConfiguration="crossDomain" 
              contract="..." behaviorConfigurations="restBehavior" /> 
  </service>
</services>

(Обратите внимание, что и служба, и конечная точка имеют прикрепленные поведения, разрешающие вызовы webHttp и httpGet соответственно, и что для привязки явно разрешен междоменный доступ).

... метод обслуживания, оформленный следующим образом:

[ServiceContract]
public interface IMyService
{
    [WebGet] // Required Attribute to allow GET
    [OperationContract]
    string MyMethod(string MyParam);
}

... и клиентский вызов с использованием JSONP:

<script type="text/javascript">
$(document).ready(function() {
    var url =  "...";
    $.getJSON(url + "?callback=?", null, function(result) { // Note crucial ?callback=?
       // Process result
    });
});
</script>
person Jude Fisher    schedule 05.11.2012
comment
Спасибо. Просто попробовал, но не сработало, ссылка на пример на стороне клиента мертва. Я попытался добавить привязки crossDomain в свой web.config, но это не сработало. - person ipohfly; 05.11.2012
comment
Просто погуглите или найдите здесь JSONP - есть множество примеров, таких как: stackoverflow.com/questions/2681466/jsonp -with-jquery Исправить только серверную часть не получится. - person Jude Fisher; 05.11.2012
comment
Также - можете ли вы показать свой код WCF? Помимо разрешения WebGet в Web.Config (как в примере выше), вам необходимо украсить свой метод WCF правильным атрибутом. - person Jude Fisher; 05.11.2012
comment
действительно спасибо за вашу помощь. Я пробовал новую настройку, но она тоже не работает, но я не пробовал использовать метод json. Я также обновил свой раздел кодов. - person ipohfly; 06.11.2012
comment
Ну наконец то! После использования JSONP (параметр обратного вызова очень важен) и он сработал !!!! Миллион спасибо! - person ipohfly; 06.11.2012

Однако это старый поток, но я хотел бы добавить свой комментарий о проблемах, с которыми я столкнулся, и о решении, которое я получил для работы с CORS. Я разрабатываю веб-сервис в следующей среде:

  1. Веб-служба WCF.
  2. Платформа .NET 3.5.
  3. Добавлен веб-сервис wcf на существующий веб-сайт asp.net.
  4. Visual Studio 2008

Большинство людей упомянули о добавлении атрибута crossDomainScriptAccessEnabled в тег под <webHttpBinding> в web.config. Я не уверен, что это работает или нет, но он недоступен в версии 3.5, поэтому у меня не было выбора. Я также обнаружил, что добавление следующих тегов в web.config будет работать ...

<httpProtocol> <customHeaders> <add name="Access-Control-Allow-Origin" value="*" /> <add name="Access-Control-Allow-Methods" value="GET" /> <add name="Access-Control-Allow-Headers" value="Content-Type, Accept" /> </customHeaders> </httpProtocol>

но не повезло ... продолжал получать 405 метод недопустимых ошибок

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

protected void Application_BeginRequest(object sender, EventArgs e)
{
    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
    if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
    {
        HttpContext.Current.Response.AddHeader("Cache-Control", "no-cache");
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST");
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept, Authorization");
        HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
        HttpContext.Current.Response.End();
    }
}

И удалите файл из web.config. Опубликуйте веб-сайт и перейдите к jquery / ajax на стороне клиента ... и вы получите данные из вызовов api. Удачи!

person RamKr    schedule 21.02.2014

Просто хотел добавить некоторые проблемы с переработкой CORS внизу - проблема в том, что если ваш ввод не поддерживает методы GET и POST, запрос OPTIONS фактически не возвращает правильные разрешенные заголовки. На самом деле он не смотрит на то, какие методы фактически разрешены в конечной точке WCF - он просто искусственно говорит, что «GET, POST» разрешены для каждой отдельной конечной точки в приложении, когда клиент выполняет запрос OPTIONS (который на самом деле является запросом клиента, что поддерживается).

Это, вероятно, нормально, если вы действительно не полагаетесь на информацию в методе OPTIONS, чтобы вернуть вам действительный список методов (как в случае с некоторыми запросами CORS), но если да, вам нужно будет сделать что-то вроде решение по этому вопросу: Как работать с Ajax Запрос JQUERY POST с собственным хостом WCF

По сути, каждая конечная точка должна реализовывать:

Webinvoke(Method="OPTIONS", UriTemplate="")

и вызвать соответствующий метод, который загружает правильные заголовки в ответ (включая соответствующий список «Access-Control-Allow-Method» для этой конечной точки) вызывающей стороне. Отстойно, что размещенные конечные точки WCF не делают этого за нас автоматически, но это обходной путь, который позволяет более точно контролировать конечную точку. В этом решении правильные заголовки ответа загружаются в реализацию конечной точки:

public void GetOptions()
    {
        // The data loaded in these headers should match whatever it is you support on the endpoint
        // for your application. 
        // For Origin: The "*" should really be a list of valid cross site domains for better security
        // For Methods: The list should be the list of support methods for the endpoint
        // For Allowed Headers: The list should be the supported header for your application

        WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Origin", "*");
        WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
        WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Headers", "Content-Type, Accept, Authorization");
    }
person jeremyh    schedule 17.03.2014

Что сработало для меня, так это включение связанных с WCF функций IIS:  введите описание изображения здесь

person ajaysinghdav10d    schedule 02.02.2021

попробуй использовать. WebInvoke(Method = "POST") вместо WebInvoke(Method = "GET")

person Hafeez Liaquat    schedule 22.12.2015