Click here to Skip to main content
15,885,546 members
Articles / Programming Languages / C# 5.0

Enabling CORS in WCF

Rate me:
Please Sign up or sign in to vote.
4.98/5 (26 votes)
21 Sep 2016CPOL5 min read 160.7K   3.6K   24   33
Enable CORS support in WCF and consuming WCF as rest API from different domain , other than WCF hosted domain.

Introduction

This is an intermediate example of WCF as REST based solution and enabling CORS access, so that this WCF service can be consumed from other domains without having cross-domain issues. I will explain more on CORS in latter section, so hold on , read through problem and solution. While developing this similar solution, I have faced issues, and did not find any helpful working article/blog, so i am posting this. Hope this will be helpful.

Background

We develop WCF service as REST service and consume that using javascript and jquery calls. This is good to start with single page application or purely javascript based application. You will never face any issue as long as wcf service hosted domain remains same as the domain where you have consumer service. The issue arises when, you started allowing other companies to consume WCF service as REST service. For e.g. you have some reporting service and exposed as REST service. You have a web portal , where this is consumed. And since this purely REST based, you want to allow 3rd party companies to consumer REST based service and show same reporting in their website. NOTE: In this case, JS used to consume WCF service will be sitting at client's domain, but WCF domain will be your domain. And this different domain will cause cross domain issue, i.e. WCF will throw error while invoking.

Using the code

Before jumping straight into code, I want to formally introduce what is REST and CORS issue.

Representational state transfer (REST) is an abstraction of the architecture of the World Wide Web; more precisely, REST is an architectural style consisting of a coordinated set of architectural constraints applied to components, connectors, and data elements, within a distributed hypermedia system. REST ignores the details of component implementation and protocol syntax in order to focus on the roles of components, the constraints upon their interaction with other components, and their interpretation of significant data elements.-- http://en.wikipedia.org/wiki/Representational_state_transfer#Framework_implementations

Cross-origin resource sharing- User agents commonly apply same-origin restrictions to network requests. These restrictions prevent a client-side Web application running from one origin from obtaining data retrieved from another origin, and also limit unsafe HTTP requests that can be automatically launched toward destinations that differ from the running application's origin. - http://www.w3.org/TR/cors/#introduction

In this example, I will use sample WCF service , that Visual studio provides. First, we will create a WCF REST service, which can accept POST request with parameter as an object. Write a simple JS based APP to consume that. And WCF service will simply return the some prefix + received object value. As we are mainly focusing to enable CORS, I have kept this very basic.

Then I will show you , where exactly error happens. After that, solution for overcoming CORS issue.

Step#1. Lets create a WCF service project, create service contract and operation contract as shown below.

[ServiceContract]
public interface IService1
{

    [OperationContract]
    [WebInvoke(UriTemplate = "/TestMethod", Method = "POST", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json
      )]
    string TestMethod(CompositeType value);

}

Step#2 Definition of CompositeType is - 

[DataContract]
public class CompositeType
{
    bool boolValue = true;
    string stringValue = "Hello ";

    [DataMember]
    public bool BoolValue
    {
        get { return boolValue; }
        set { boolValue = value; }
    }

    [DataMember]
    public string StringValue
    {
        get { return stringValue; }
        set { stringValue = value; }
    }
}

Step#3 Then, create service class. Following is the code for this.

public class Service1 : IService1

{
    public string TestMethod(CompositeType value)
    {
        return string.Format("You entered: {0}", value.StringValue);
    }
}

Step#4 Assume it is hosted somewhere ( www.example1.com ) and test with fiddler whether it works. Following is the result.

Image 1

 

Hurray!, it is working fine, see Result - 200 status.

Step#5 I have a simple javascript ( this will be in a HTML file) to invoke this REST based method.  The html file is hosted in - http://localhost Source code for javascript part in html file.

$(document).ready(function () {
	$("button").click(function () {
		alert("clicked");
		var data = $("#txt").val();
		var postdata = {};
		var data_obj = {"BoolValue" : "true" , "StringValue": data}
		postdata["value"] =  data_obj; 

		var url = "https://tmdev01.tm00.com/testwcf/service1.svc/TestMethod";
		$.ajax({
			type: "POST",
			url: url,
			contentType: "application/json; charset=utf-8",
			data: JSON.stringify(postdata),
			dataType: "json",
			success: function(data) {console.log(data);},
			error: function(a,b,c) {console.log(a);}
		});
	});
});

-----------------HTML Part-------------

Enter something <input id="txt" type="text" /><button>Get WCF data</button>

Now, when i execute this javascript it will throw error. Following is the error message from browser console.

Quote:

 OPTIONS https://www.example.com/wcfv1/service1.svc/TestMethod 
test1.html:1 XMLHttpRequest cannot load https://www.example1.com/wcfv1/service1.svc/TestMethod. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access. The response had HTTP status code 405.

Following is the browser request payload info.

Image 2

 

And it is not working anymore with other domain javascript call :( .

If you closely look into this - we are invoking WCF with "POST" request , but it shows request method as "OPTIONS". This is because, POST, PUT, DELETE methods are unsafe methods and cross domain requests first makes a preflight request i.e. OPTIONS request to see if that succeeds means server responds/sends OK signal to that , then only it will again make actual POST request.

Also, note that it sends various request headers such as "Access-Control-Request-Headers", "Access-Control-Request-Method".

What it means? -  We as wcf service developer need to responds to that OPTIONS http request.

How to do that? -  Add global.asax file and add following code to Application_BeginRequest. Following is the code snippet.

protected void Application_BeginRequest(object sender, EventArgs e)
{
    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "http://localhost");
    if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
    {
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "POST, PUT, DELETE");

        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
        HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
        HttpContext.Current.Response.End();
    }
}

As you can see from above, i am allowing origin to "http://localhost", so that if javascript is placed in this domain and that is making call to WCF, then it will be allowed. Also i have added request response header that we should send as part of OPTIONS Request header.

This is extremely important decision :  You can always use "*" for Access-Control-Allow-Origin, but for security reason that is discouraged. Because you are opening access to all to invoke your WCF server as REST Service from anywhere. Whereas you should know, to whom you are providing access for CORS and put those domains here only.

This is basic thing i am doing here, you can make those thing configurable.

So we are done with this setup, and i am going to deploy this solution, see if that helps.

Conclusion:

Now, i am using same javascript as above , and just hosted changed WCF code into some other virtual directory(testwcf). So when i issue ajax request, see that it has made 2 requests - OPTIONS, POST. Refer below screenshot.

Image 3

 

We will analyse both request details, so first, see what is OPTIONS request's response and how that is different from 1st attempt with non-CORS WCF.

Image 4

 

As you can see that, now our WCF service responded with all required response headers such as "access-control-allow-* " . - Note: we have done these in global.asax.

So when this request succeed , then browser made 2nd request i.e. actual POST . Lets check the details of that.

Image 5

 

Now, you can see that, it actually made request payload and see that response header ( see Status code- 200 OK), it succeed and has some content-length.

Points of Interest

If you find it interesting and have some suggestion , put a comment , am i ready to interact with you. 

Download source code here.

 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
India India
Developing web based application since last 5 years, also interested in designing application with optimized used of available tech stacks, as well as apply those and real life experience to help out friends, colleagues,communities such as this or other forums.

MCSD (2013) certified developer.

Reach me - http://about.me/arindamnayak

Comments and Discussions

 
GeneralMy vote of 5 Pin
Member 152265251-Jun-21 9:37
Member 152265251-Jun-21 9:37 
PraiseWholehearted thank you Pin
varma_vizag9-Aug-20 18:59
varma_vizag9-Aug-20 18:59 
QuestionTnaks a lot Pin
Member 1465291412-Nov-19 3:48
Member 1465291412-Nov-19 3:48 
QuestionCORS for classic WCF Pin
Suman Padhy26-Jun-18 17:01
Suman Padhy26-Jun-18 17:01 
PraiseThank You! Pin
Member 136651646-Feb-18 20:07
Member 136651646-Feb-18 20:07 
QuestionCORS handling will not work if WCF is self hosted Pin
Nitin Singh India18-Apr-17 2:56
Nitin Singh India18-Apr-17 2:56 
AnswerRe: CORS handling will not work if WCF is self hosted Pin
ArindamNayak23-Apr-17 20:00
professionalArindamNayak23-Apr-17 20:00 
QuestionWorked like a charm Pin
ZeroCode710-Jan-17 1:53
professionalZeroCode710-Jan-17 1:53 
Question... almost working Pin
S.Mardaus29-Sep-16 12:07
S.Mardaus29-Sep-16 12:07 
AnswerRe: ... almost working Pin
ArindamNayak29-Sep-16 20:13
professionalArindamNayak29-Sep-16 20:13 
GeneralRe: ... almost working Pin
S.Mardaus30-Sep-16 8:53
S.Mardaus30-Sep-16 8:53 
GeneralGot it! Pin
S.Mardaus30-Sep-16 9:59
S.Mardaus30-Sep-16 9:59 
GeneralRe: Got it! Pin
ArindamNayak30-Sep-16 19:06
professionalArindamNayak30-Sep-16 19:06 
QuestionThank you! Pin
KenGraci22-Jul-16 15:35
KenGraci22-Jul-16 15:35 
Question400(bad request) . when hosted the webservice in iis.. Pin
Member 1145806619-Nov-15 22:36
Member 1145806619-Nov-15 22:36 
AnswerRe: 400(bad request) . when hosted the webservice in iis.. Pin
ArindamNayak10-Dec-15 1:56
professionalArindamNayak10-Dec-15 1:56 
QuestionCORS in Chrome Pin
thulani.moyana20-Oct-15 4:51
thulani.moyana20-Oct-15 4:51 
AnswerRe: CORS in Chrome Pin
ArindamNayak20-Oct-15 19:57
professionalArindamNayak20-Oct-15 19:57 
QuestionThanks a lot! Pin
Vladyslav Fedoniuk30-Sep-15 23:18
Vladyslav Fedoniuk30-Sep-15 23:18 
QuestionNot working for me Pin
Member 1153932519-Mar-15 9:28
Member 1153932519-Mar-15 9:28 
AnswerRe: Not working for me Pin
ArindamNayak19-Mar-15 19:11
professionalArindamNayak19-Mar-15 19:11 
When you catch error, the handler should have 3 params, I am talking about ajax success/error callbacks. Usually these type of errors ( like status 200, but error handler hit) occurs when there is data type mismatch with expected type happens, so to make it dead simple, use string type instead of composite type and try again.
GeneralRe: Not working for me Pin
Member 1153932520-Mar-15 8:13
Member 1153932520-Mar-15 8:13 
GeneralRe: Not working for me Pin
ArindamNayak20-Mar-15 19:43
professionalArindamNayak20-Mar-15 19:43 
BugAlready published under Blog category Pin
Akhil Mittal23-Nov-14 21:41
professionalAkhil Mittal23-Nov-14 21:41 
GeneralRe: Already published under Blog category Pin
ArindamNayak23-Nov-14 21:48
professionalArindamNayak23-Nov-14 21:48 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.