Как добавить поддержку перекрестных доменов в службу WCF - программирование

Как добавить поддержку перекрестных доменов в службу WCF

Я пытаюсь разрешить POST-запросы из моего приложения javascript, размещенного на localhost: 80, в службу WCF REStful, размещенную на другом порту, но почему-то это не работает. Я попытался добавить пользовательские свойства в заголовок, а также добавить его программным способом в моем сервисе JSONData, но я все еще получаю "405 Method not allowed" в своем ответе. Какой здесь подход?

Это мой интерфейс:

namespace RestService
{
    public class RestServiceImpl : IRestServiceImpl
    {
        #region IRestServiceImpl Members

        public string JSONData()
        {
            HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
            return "Your POST request";
        }

        #endregion
    }
}

и служебный код:

using System.ServiceModel;
using System.ServiceModel.Web;
using System.Web.Script.Services;

namespace RestService
{

    [ServiceContract]
    public interface IRestServiceImpl
    {
        [OperationContract]
        [ScriptMethod]
        [WebInvoke(Method = "POST",
            ResponseFormat = WebMessageFormat.Json,
            BodyStyle = WebMessageBodyStyle.Bare,
            UriTemplate = "export")]
        string JSONData();
    }
}

И, наконец, config:

<?xml version="1.0"?>
<configuration>

  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel>
    <services>
      <service name="RestService.RestServiceImpl" behaviorConfiguration="ServiceBehaviour">
        <endpoint address ="" binding="webHttpBinding" contract="RestService.IRestServiceImpl" behaviorConfiguration="web">
        </endpoint>
      </service>
    </services>

    <behaviors>
      <serviceBehaviors>
        <behavior name="ServiceBehaviour">
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
      <endpointBehaviors>
        <behavior name="web">
          <webHttp/>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
    <httpProtocol>
      <customHeaders>
         <add name="Access-Control-Allow-Origin" value="*" />
      </customHeaders>
</httpProtocol>  
  </system.webServer>

</configuration>
4b9b3361

Ответ 1

Это работало лучше для меня, чем версия Web.config:

Создать Global.asax

Добавьте этот метод в Global.asax.cs:

using System.Web;

namespace StackOverflow
{
    public class Global : System.Web.HttpApplication
    {
        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("Access-Control-Allow-Methods", "GET, POST");
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
                HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
                HttpContext.Current.Response.End();
            }
        }
    }
}

Ссылка: http://www.dotnet-tricks.com/Tutorial/wcf/X8QN260412-Calling-Cross-Domain-WCF-Service-using-Jquery.html

Ответ 2

Добавьте эти узлы в свой Web.config:

<configuration>
  <system.webServer>
    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*"/>
        <add name="Access-Control-Allow-Headers" value="Content-Type, Accept" />
        <add name="Access-Control-Allow-Methods" value="POST,GET,OPTIONS" />
        <add name="Access-Control-Max-Age" value="1728000" />
      </customHeaders>
    </httpProtocol>
  </system.webServer>
</configuration>

Ссылка: http://theagilecoder.wordpress.com/2014/07/07/wcf-and-cors-no-access-control-allow-origin-header-is-present-on-the-requested-resource/

Ответ 3

Включение CORS для запросов, отличных от GET, требует больше, чем просто настройки заголовка Access-Control-Allow-Origin - ему также необходимо иметь дело с запросами предполетных запросов, которые являются OPTIONS запросами, которые запрашивают у сервера, безопасно ли выполнять операции, которые могут потенциально измениться (например, POST, PUT, DELETE) перед отправкой фактического запроса.

Я написал сообщение в блоге о добавлении поддержки CORS для WCF. Это не самая простая реализация, но, надеюсь, код в сообщении можно просто скопировать/вставить в ваш проект. Сообщение можно найти на http://blogs.msdn.com/b/carlosfigueira/archive/2012/05/15/implementing-cors-support-in-wcf.aspx.

Ответ 4

Следующий код .NET(global.asax) имеет важное отличие, заключающееся в том, что вместо * можно лучше отследить домен Origin, поскольку это позволяет проводить аутентификацию через CORS (например, NTLM/Kerberos), а также предполетную,

void Application_BeginRequest(object sender, EventArgs e)
{
    if (Request.HttpMethod == "OPTIONS")
    {
        Response.AddHeader("Access-Control-Allow-Methods", "GET, POST");
        Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
        Response.AddHeader("Access-Control-Max-Age", "1728000");
        Response.End();
    }
    else
    {
        Response.AddHeader("Access-Control-Allow-Credentials", "true");

        if (Request.Headers["Origin"] != null)
            Response.AddHeader("Access-Control-Allow-Origin" , Request.Headers["Origin"]);
        else
            Response.AddHeader("Access-Control-Allow-Origin" , "*");
    }
}