Вызов службы собственного хоста WCF с использованием Ajax: метод 405 не разрешен Ошибка - PullRequest
0 голосов
/ 12 июня 2019

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

У меня есть собственная служба WCF в приложении WinForms.

Код:

[ServiceContract]
public interface IMathService
{
    [WebInvoke(Method = "GET",
        UriTemplate = "Add/{num1}",
        RequestFormat = WebMessageFormat.Json,
        ResponseFormat = WebMessageFormat.Json)]
    [OperationContract]
    int Add(string num1);
}

public class MathService : IMathService
{
    public int Add(string num1)
    {
        return Convert.ToInt32(num1) + 1;
    }
}
public Form1()
{
    InitializeComponent();
    WebServiceHost testHost = new WebServiceHost(typeof(MathService));
    testHost.Open();

}

App.Config:

<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
  </startup>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="ServiceBehavior">
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
      <endpointBehaviors>
        <behavior name="EndpBehavior">
          <webHttp/>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <services>
      <service behaviorConfiguration="ServiceBehavior" name="S3SelfHost.MathService">
        <endpoint address="http://localhost:8181/MathService" binding="webHttpBinding"

            contract="S3SelfHost.IMathService" behaviorConfiguration="EndpBehavior"/>
      </service>
    </services>
  </system.serviceModel>
</configuration>

У меня есть обычная HTML-страница и файл js, из которого я пытаюсь вызвать эту службу, которая работает только на моем локальном компьютере.

JS:

$("#btnAdd").click(function () {
    jQuery.support.cors = true;
    $.ajax({
        type: "POST",
        contentType: "application/json; charset=UTF-8; charset-uf8",
        url: 'http://localhost:8181/MathService/Add/1',
        success: function (data) {
            $("#result").val(result);
        },
        error: function (result) {
            alert(result);
        }
    });

});

Если я напрямую нажимаю URL-адрес хостинга в браузере, он показывает правильный результат, но когда я использую тот же URL-адрес в коде js, в консоли отображается следующая ошибка.

Доступ к XMLHttpRequest в 'http://localhost:8181/MathService/Add/1' из источника 'http://localhost' заблокирован политикой CORS: Ответ на предполетный запрос не проходит проверку контроля доступа: Нет Заголовок «Access-Control-Allow-Origin» присутствует в запрошенном ресурс.

И в заголовке ответа Fiddler это показывает

405 Метод не разрешен

1 Ответ

0 голосов
/ 13 июня 2019

Для службы Self-host WCF, созданной WebHttpBinding, мы могли бы использовать следующий код для включения поддержки CORS.
См.

    using System;
using System.Collections.Generic;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Configuration;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Web;

Расширение поведения конечной точки.

public class CustomHeaderMessageInspector : IDispatchMessageInspector
    {
        Dictionary<string, string> requiredHeaders;
        public CustomHeaderMessageInspector(Dictionary<string, string> headers)
        {
            requiredHeaders = headers ?? new Dictionary<string, string>();
        }
        public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel, InstanceContext instanceContext)
        {
            return null;
        }

        public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
        {
            var httpHeader = reply.Properties["httpResponse"] as HttpResponseMessageProperty;
            foreach (var item in requiredHeaders)
            {
                httpHeader.Headers.Add(item.Key, item.Value);
            }

        }
    }
    public class CustomContractBehaviorAttribute : BehaviorExtensionElement, IEndpointBehavior
    {
        public override Type BehaviorType => typeof(CustomContractBehaviorAttribute);

        public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
        {
        }

        public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        {
        }

        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
        {
            var requiredHeaders = new Dictionary<string, string>();

            requiredHeaders.Add("Access-Control-Allow-Origin", "*");
            requiredHeaders.Add("Access-Control-Max-Age", "1728000");
            requiredHeaders.Add("Access-Control-Request-Method", "POST,GET,PUT,DELETE,OPTIONS");
            requiredHeaders.Add("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization, Pragma, Cache-Control");
            endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new CustomHeaderMessageInspector(requiredHeaders));
        }

        public void Validate(ServiceEndpoint endpoint)
        {

        }

        protected override object CreateBehavior()
        {
            return new CustomContractBehaviorAttribute();
        }
    }

Примените его в конечной точке службы.

      <endpointBehaviors>
        <behavior name="EndpBehavior">
          <webHttp/>
          <CorsBehavior />
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <services>
      <service behaviorConfiguration="ServiceBehavior" name="YourNamespace.MathService">
        <endpoint address="http://localhost:8181/MathService" binding="webHttpBinding"
            contract="YourNamespace.IMathService" behaviorConfiguration="EndpBehavior"/>
      </service>
    </services>
    <extensions>
      <behaviorExtensions>
        <add name="CorsBehavior" type="YourNamespace.CustomContractBehaviorAttribute, YourNamespace" />
      </behaviorExtensions>
    </extensions>
  </system.serviceModel>

Клиент.

                //10.157.13.70 is the host that runs the Winform application.
   var serviceuri = "http://10.157.13.70:8181/MathService/add/34";
            $.ajax({
                method:"Get",
                url:serviceuri,
                //contentType:"application/x-www-form-urlencoded",
                success:function(data){
                    console.log(data);
                }
            }).done(function(data){
                console.log(data);
            }).fail(function(jqxhr,textstatus,err){
                console.log(err);
            })

Результат. enter image description here
Не стесняйтесь, дайте мне знать, если проблема все еще существует.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...