Instructor-led online courses : ASP.NET Core 2.2, Angular 7, and ASP.NET Core Design Patterns. Read more...

Enable CORS in ASP.NET Core API

Browsers do not allow cross origin communication for security reasons. This means if an ASP.NET Core web API housed in one web app is called by JavaScript code running as a part of another web app, the communication attempt will fail. However, you can alter this default behavior by adding some configuration in your API application. To that end this article discusses how that task can be accomplished.

Note : If you are unfamiliar with CORS I suggest you go here to familiarize with the basics.

In order to illustrate how CORS related configuration can be added to an API, you need to create a new ASP.NET Core API project and an ASP.NET Core web application project. The web app acts as a client to the API.

Now, go ahead and modify the API controller as shown below:

[Route("api/[controller]")]
[ApiController]
public class CountriesController : ControllerBase
{

    [HttpGet]
    public ActionResult<IEnumerable<string>> Get()
    {
        return new string[] { "USA", "UK", "India" };
    }
}

Here, the CountriesController contains just the Get() action that returns a list of countries. Run the API and confirm that countries are returned from the Get() action as expected.

Now, open the client web app and write the following piece of jQuery code inside the Index.cshtml. The jQuery code that calls the above API.

$(document).ready(function () {

    var options = {};
    options.url = "http://localhost:49313/
api/countries";
    options.type = "GET";
    options.dataType = "json";
    options.success = function (countries) {
        for (var i = 0; i < countries.length; i++) {
            $("#response").append("<h2>" + 
countries[i] + "</h2>");
            console.log(countries[i]);
        }
    };
    options.error = function (a, b, c) {
        console.log(a);
        console.log(b);
        console.log(c);
    };

    $.ajax(options);
});

The above code uses jQuery Ajax to invoke the API. Notice that the URL specified in the options points to the API residing in the another web application (the API project). I won't go into the details of this code since it's quite straightforward. It is suffice to say that the jQuery code invokes the API using $.ajax() method and displays the returned countries in a <div> element with ID of response.

At this stage your Solution Explorer should resemble this:

Next, run the API project followed by the client application. Try to hit /Home/Index using the browser's address bar. You will find that nothing is shown in the browser because of this error:

This error occurs because currently the API is not configured to deal with CORS requests. Let's fix this issue by adding the required configuration.

Defining CORS policies

Go to the API project and open its Startup class. Add the following code in the ConfigureServices() method.

public void ConfigureServices(IServiceCollection services)
{
    services.AddCors(options =>
    {
        options.AddDefaultPolicy(
            builder =>
            {

                builder
                .AllowAnyOrigin()
                .AllowAnyMethod()
                .AllowAnyHeader();
            });

        options.AddPolicy("MyCORSPolicy",
            builder =>
            {
                builder.WithOrigins("http://localhost:49373")
                                    .AllowAnyHeader()
                                    .AllowAnyMethod();
            });

    });
    services.AddMvc().AddNewtonsoftJson();
}

The AddCors() method registers CORS to the services collection. Inside, we define two CORS policies - default policy and a policy named MyCORSPolicy. This is done using AddDefaultPolicy() and AddPolicy() methods respectively.

The default policy sets the default CORS configuration for the application. In the above example, we specify that incoming request can belong to any origin, it may use any HTTP verb, and any HTTP header. This is done using AllowAnyOrigin(), AllowMethod(), and AllowAnyHeader() methods.

Then we create a custom policy called MyCORSPolicy. This policy allows only a specific host (http://localhost:49373, make sure to change it as per your client app's port) to invoke the API. Moreover, the policy specifies that any HTTP verb can be used and also the HTTP headers.

There is a counterpart of AllowAnyXXXXXXX() methods. You will see a set of WithXXXXXXX() methods that will allow you to configure specific hosts, methods, and headers.

So far so good.

Using CORS policies

Now we will tell the framework to use our policies. To do so, go to the Configure() method and write the following code in it:

public void Configure(IApplicationBuilder app, 
IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseCors("MyCORSPolicy");

    app.UseRouting(routes =>
    {
        routes.MapApplication();
    });
    app.UseAuthorization();
}

The UseCors() method allows you to wire the policy into the middleware chain. Here we specified that we want to use MyCORSPolicy defined earlier. If you wish to use the default policy you would have said:

app.UseCors();

 Ok. Now run the API and the client application. This time the client application should be able to make a successful call to the API.

Enabling CORS for a specific action or controller

In the preceding example you enabled CORS at a global level so that all the APIs in the project support CORS. However, at times you may want to enable CORS at a narrow scope, say a particular action or controller. You can accomplish the task using [EnableCors] attribute.

To use [EnableCors] attribute remove the UseCors() call from the Configure() method. Then go to the Countries API and decorate the Get() action with [EnableCors] as shown below:

[HttpGet]
[EnableCors("MyCORSPolicy")]
public ActionResult<IEnumerable<string>> Get()
{
    return new string[] { "USA", "UK", "India" };
}

In this case the [EnableCors] attribute specifies that we want to use MyCORSPolicy policy defined earlier. If you would like to use the default policy the usage would be:

[HttpGet]
[EnableCors]
public ActionResult<IEnumerable<string>> Get()
{
    return new string[] { "USA", "UK", "India" };
}

You can add [EnableCors] to individual actions or controller or page model enable CORS to the underlying target. There is also counterpart of [EnableCors] - the [DisableCors] attribute. The [DisableCors] attribute disables CORS support for a particular action or controller.

You may read more details about enabling CORS in ASP.NET here.

That's it for now! Keep coding!!


Bipin Joshi is a software consultant, trainer, author, yoga mentor, and spiritual guide having 24+ years of experience in software development, consulting, and training. He conducts instructor-led online training courses in ASP.NET Core, ASP.NET MVC, and Design Patterns for individuals and small groups. He is a published author and has authored or co-authored books for Apress and Wrox press. Having embraced the Yoga way of life he also teaches Ajapa Yoga to interested individuals. To know more about him click here.

Get article updates : Facebook  Twitter  LinkedIn

Posted On : 11 March 2019


Tags : ASP.NET ASP.NET Core MVC C# Visual Studio


Subscribe to our newsletter

Get monthly email updates about new articles, tutorials, code samples, and how-tos getting added to our knowledge base.

  

Receive Weekly Updates