gandil
gandil

Reputation: 5418

Calling WCF Service from ASP.NET MVC via Ajax (CORS)

I have a WCF service which is run on a port (25537) and also I have a MVC application. From MVC application I make post call to WCF service.

I got error :

OPTIONS http://mylocal.com:25537/Authentication Request header field Content-Type is not allowed by Access-Control-Allow-Headers.

I had try to many options but nothing changed.

To Global.asax

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

To Web.Config

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

Nothing changed.

Any idea?

Thanks in advance.

Upvotes: 1

Views: 1054

Answers (2)

Alex Erygin
Alex Erygin

Reputation: 3230

You should make some configuration both on js-side and wcf-side

on js:

function post(type, data, timeout) {
    return $.ajax({
        url: createUrl(POST, type),
        type: POST,
        data: JSON.stringify(data),
        contentType: "application/json",
        crossDomain: true,//<<<<-------------It`s here!
        processData: false,
        dataType: "json",
        timeout: timeout
    });
}

app.config on wcf-side:

  <system.serviceModel>

    <extensions>
      <behaviorExtensions>
        <add name="crossOriginResourceSharingBehavior" type="Nelibur.ServiceModel.Behaviors.EnableCrossOriginResourceSharingBehavior, Nelibur" />
      </behaviorExtensions>
    </extensions>
...
    <services>
      <service name="Nelibur.ServiceModel.Services.Default.JsonServicePerCall">
        <host>
          <baseAddresses>
            <add baseAddress="http://127.0.0.1:61111/webhost" />
            <add baseAddress="https://127.0.0.1:61112/webhost" />
          </baseAddresses>
        </host>
        <endpoint binding="webHttpBinding"
                  contract="Nelibur.ServiceModel.Contracts.IJsonService" behaviorConfiguration="jsonBehavior" bindingConfiguration="webHttpBinding"/>
      </service>
    </services>
    <behaviors>
      <endpointBehaviors>
        <behavior name="jsonBehavior">
          <webHttp />
          <crossOriginResourceSharingBehavior />
        </behavior>
      </endpointBehaviors>
    </behaviors>
  </system.serviceModel>

Behavior class on WCF-service side:

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

namespace Nelibur.ServiceModel.Behaviors
{
    /// <summary>
    ///     Provides CORS support.
    /// </summary>
    public class EnableCrossOriginResourceSharingBehavior : BehaviorExtensionElement, IEndpointBehavior
    {
        /// <summary>
        ///     Gets the type of behavior.
        /// </summary>
        /// <returns>
        ///     A <see cref="T:System.Type" />.
        /// </returns>
        public override Type BehaviorType
        {
            get { return typeof (EnableCrossOriginResourceSharingBehavior); }
        }

        /// <summary>
        ///     Implement to pass data at runtime to bindings to support custom behavior.
        /// </summary>
        /// <param name="endpoint">The endpoint to modify.</param>
        /// <param name="bindingParameters">The objects that binding elements require to support the behavior.</param>
        public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
        {
        }

        /// <summary>
        ///     Implements a modification or extension of the client across an endpoint.
        /// </summary>
        /// <param name="endpoint">The endpoint that is to be customized.</param>
        /// <param name="clientRuntime">The client runtime to be customized.</param>
        public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        {
        }

        /// <summary>
        ///     Implements a modification or extension of the service across an endpoint.
        /// </summary>
        /// <param name="endpoint">The endpoint that exposes the contract.</param>
        /// <param name="endpointDispatcher">The endpoint dispatcher to be modified or extended.</param>
        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
        {
            var requiredHeaders = new Dictionary<string, string>();

            requiredHeaders.Add("Access-Control-Allow-Origin", "*");
            requiredHeaders.Add("Access-Control-Request-Method", "POST,GET,OPTIONS");
            requiredHeaders.Add("Access-Control-Allow-Headers", "X-Requested-With,Content-Type");

            endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new CustomHeaderMessageInspector(requiredHeaders));
        }

        /// <summary>
        ///     Implement to confirm that the endpoint meets some intended criteria.
        /// </summary>
        /// <param name="endpoint">The endpoint to validate.</param>
        public void Validate(ServiceEndpoint endpoint)
        {
        }

        /// <summary>
        ///     Creates a behavior extension based on the current configuration settings.
        /// </summary>
        /// <returns>
        ///     The behavior extension.
        /// </returns>
        protected override object CreateBehavior()
        {
            return new EnableCrossOriginResourceSharingBehavior();
        }
    }
}

You also have to include next operation in your service contract:

/// <summary>
/// Helper method for CORS support.
/// </summary>
[OperationContract]
[WebInvoke(Method = "OPTIONS", UriTemplate = "*")]
void GetOptions();

That`s all. Hope this help.

Upvotes: 1

Rachit Patel
Rachit Patel

Reputation: 862

To access WCF service across the cross domain you must have to allow crossDomainScriptAccessEnabled="true" for your binding.

I am sharing a very good blog and I am sure that, this will help you to understand access WCF service across the cross domain and difference between Jquery Ajax and Jsonp method.

http://www.bendewey.com/index.php/186/using-jsonp-with-wcf-and-jquery

Upvotes: 0

Related Questions