Click here to Skip to main content
15,886,110 members
Articles / Web Development / ASP.NET / ASP.NETvNext

Enable Cross-origin Resource Sharing (CORS) in ASP.NET Core

Rate me:
Please Sign up or sign in to vote.
5.00/5 (6 votes)
27 Oct 2016CPOL3 min read 32.4K   150   8   1
In this article, we will focus on how to enable CORS in ASP.NET Core application, get knowledge about CORS policy how we can share resource through different origin.

The following topics will be discussed in this article:

  • What is CORS?
  • Create .NET Core WebApi Application
    • Add Packages
    • Add Database Connection
    • Enable CORS
  • Publishing to IIS
  • Share Through .NET Core Sample Application

Introduction

First let's get introduced to CORS, from Wikipedia, Cross-origin resource sharing (CORS) is a mechanism that allows restricted resources (e.g. fonts) on a web page to be requested from another domain outside the domain from which the resource originated. Get more details from docs.asp.net. Ok let's get started with our topic with a sample application.

Create New Application

Open Visual Studio 2015, then go top menu and Click > File > New > Project.

core_4

Choose Web API template.

core_5

Finally .NET Core Welcome page will appear. Read more about .NET Core.

core_6

First, we need to add required Packages to sample application, here we have added those packages listed below in project.json file. After putting all those packages in our project config file, they will automatically be added to our application by IDE.

project.json
JavaScript
//EntityFrameworkCore
"Microsoft.EntityFrameworkCore.SqlServer": "1.0.1",
"Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final",
"Microsoft.EntityFrameworkCore.SqlServer.Design": "1.0.1",
"Microsoft.EntityFrameworkCore": "1.0.1",

//Cross Origin Resource Sharing
"Microsoft.AspNetCore.Cors": "1.0.0"

Now let's add database connection to our application. Open appsettings.json file, we have put down our database connection string here as you can see from the below code section.

appsettings.json
JavaScript
{
  "ConnectionStrings": {
    "dbConn": "Server=DESKTOP-JAKRV2S;Database=PhoneBook;Trusted_Connection=True;
    MultipleActiveResultSets=true"
  },
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Information"
    }
  }
}

After that, we need to call it in our application middleware in Startup.cs.

C#
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    
    //Add database services.
    var connectionString = this.Configuration.GetConnectionString("dbConn");
    services.AddDbContext<PhoneBookContext>
    (options => options.UseSqlServer(connectionString));
}

Now we are going to add & enable CORS to our sample API application. Open Startup.cs file from solution explorer, as you can see I have added the CORS service in ConfigureServices method to enable it by getting called on run-time. Here, we have also specified different CORS enable policy by using CorsPolicyBuilder. You may test by enabling different types with this sample application.

Startup.cs: ConfigureServices

JavaScript
services.AddCors(
    options => options.AddPolicy("AllowCors",
    builder =>
    {
        builder
        //.WithOrigins("http://localhost:4456") //AllowSpecificOrigins;
        //.WithOrigins("http://localhost:4456", 
        "http://localhost:4457") //AllowMultipleOrigins;
        .AllowAnyOrigin() //AllowAllOrigins;

        //.WithMethods("GET") //AllowSpecificMethods;
        //.WithMethods("GET", "PUT") //AllowSpecificMethods;
        //.WithMethods("GET", "PUT", "POST") //AllowSpecificMethods;
        .WithMethods("GET", "PUT", 
        "POST", "DELETE") //AllowSpecificMethods;
        //.AllowAnyMethod() //AllowAllMethods;

        //.WithHeaders("Accept", "Content-type", "Origin", "X-Custom-Header");  
        //AllowSpecificHeaders;
        .AllowAnyHeader(); //AllowAllHeaders;
    })
);

Let's Separate the Code

With Origin: Enable CORS with All, Multiple or Specific Origin

Allow Specific Origin
C#
builder.WithOrigins("http://localhost:4456")
Allow Multiple Origins
C#
builder.WithOrigins("http://localhost:4456", "http://localhost:4457")
Allow All Origins
C#
builder.AllowAnyOrigin()

With Methods: Enable CORS with All, Multiple or Specific Methods

Allow Specific Methods
C#
builder.WithMethods("GET", "PUT", "POST", "DELETE")
Allow All Methods
C#
builder.AllowAnyMethod()

With Headers: Enable CORS with All or Specific Headers

Allow Specific Headers
C#
builder.WithHeaders("Accept", "Content-type", "Origin", "X-Custom-Header")
Allow All Headers
C#
builder.AllowAnyHeader()

After that, we have enabled CORS for your application using an extension method "UseCors".

Startup.cs: Configure

JavaScript
//Enable CORS policy "AllowCors"
app.UseCors("AllowCors");

Finally the Full Startup.cs:

C#
public class Startup
{
    public Startup(IHostingEnvironment env)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);

        if (env.IsEnvironment("Development"))
        {
            // This will push telemetry data through Application Insights pipeline faster, 
            // allowing you to view results immediately.
            builder.AddApplicationInsightsSettings(developerMode: true);
        }

        builder.AddEnvironmentVariables();
        Configuration = builder.Build();
    }

    public IConfigurationRoot Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container
    public void ConfigureServices(IServiceCollection services)
    {

        //Add database services.
        var connectionString = this.Configuration.GetConnectionString("dbConn");
        services.AddDbContext<PhoneBookContext>
        (options => options.UseSqlServer(connectionString));

        // Add framework services.
        services.AddApplicationInsightsTelemetry(Configuration);

        services.AddMvc();

        //Add CORS services.
        //services.Configure<MvcOptions>(options =>
        //{
        //    options.Filters.Add
        //    (new CorsAuthorizationFilterFactory("AllowSpecificOrigin"));
        //});

        services.AddCors(
            options => options.AddPolicy("AllowCors",
            builder =>
            {
                builder
                //.WithOrigins("http://localhost:4456") //AllowSpecificOrigins;
                //.WithOrigins("http://localhost:4456", "http://localhost:4457") 
                //AllowMultipleOrigins;
                .AllowAnyOrigin() //AllowAllOrigins;

                //.WithMethods("GET") //AllowSpecificMethods;
                //.WithMethods("GET", "PUT") //AllowSpecificMethods;
                //.WithMethods("GET", "PUT", "POST") 
                //AllowSpecificMethods;
                .WithMethods("GET", "PUT", "POST", "DELETE") 
                //AllowSpecificMethods;
                //.AllowAnyMethod() //AllowAllMethods;

                //.WithHeaders("Accept", 
                //"Content-type", "Origin", "X-Custom-Header");  
                //AllowSpecificHeaders;
                .AllowAnyHeader(); //AllowAllHeaders;
            })
        );
    }

    // This method gets called by the runtime. 
    // Use this method to configure the HTTP request pipeline
    public void Configure
    (IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        loggerFactory.AddConsole(Configuration.GetSection("Logging"));
        loggerFactory.AddDebug();

        app.UseApplicationInsightsRequestTelemetry();

        app.UseApplicationInsightsExceptionTelemetry();

        app.UseMvc();

        //Enable CORS policy "AllowCors"
        app.UseCors("AllowCors");
    }
}

MVC WebApi: Here are a list of required namespaces.

C#
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Cors;
using CrossOrigin.WebService.Models.DbEntities;
using Microsoft.EntityFrameworkCore;

API Controller: Here, we are applying specific CORS policy on APiController. It can also be applied on per action based or globally for all controllers based.

C#
[EnableCors("AllowCors"), Route("api/[controller]")]
public class ContactController : Controller
{
    private PhoneBookContext _ctx = null;
    public ContactController(PhoneBookContext context)
    {
        _ctx = context;
    }

    // GET: api/Contact/GetContact
    [HttpGet("GetContact"), Produces("application/json")]
    public async Task<object> GetContact()
    {
        List<Contacts> contacts = null;
        object result = null;
        try
        {
            using (_ctx)
            {
                contacts = await _ctx.Contacts.ToListAsync();
                result = new
                {
                    contacts
                };
            }
        }
        catch (Exception ex)
        {
            ex.ToString();
        }
        return contacts;
    }

    // GET api/Contact/GetContactByID/5
    [HttpGet("GetContactByID/{id}"), Produces("application/json")]
    public async Task<Contacts> GetContactByID(int id)
    {
        Contacts contact = null;
        try
        {
            using (_ctx)
            {
                contact = await _ctx.Contacts.FirstOrDefaultAsync(x => x.ContactId == id);
            }
        }
        catch (Exception ex)
        {
            ex.ToString();
        }
        return contact;
    }

    // POST api/Contact/PostContact
    [HttpPost, Route("PostContact"), Produces("application/json")]
    public async Task<object> PostContact([FromBody]Contacts model)
    {
        object result = null; string message = "";
        if (model == null)
        {
            return BadRequest();
        }
        using (_ctx)
        {
            using (var _ctxTransaction = _ctx.Database.BeginTransaction())
            {
                try
                {
                    _ctx.Contacts.Add(model);
                    await _ctx.SaveChangesAsync();
                    _ctxTransaction.Commit();
                    message = "Saved Successfully";
                }
                catch (Exception e)
                {
                    _ctxTransaction.Rollback();
                    e.ToString();
                    message = "Saved Error";
                }

                result = new
                {
                    message
                };
            }
        }
        return result;
    }

    // PUT api/Contact/PutContact/5
    [DisableCors, HttpPut, Route("PutContact/{id}")]
    public async Task<object> PutContact(int id, [FromBody]Contacts model)
    {
        object result = null; string message = "";
        if (model == null)
        {
            return BadRequest();
        }
        using (_ctx)
        {
            using (var _ctxTransaction = _ctx.Database.BeginTransaction())
            {
                try
                {
                    var entityUpdate = _ctx.Contacts.FirstOrDefault(x => x.ContactId == id);
                    if (entityUpdate != null)
                    {
                        entityUpdate.FirstName = model.FirstName;
                        entityUpdate.LastName = model.LastName;
                        entityUpdate.Phone = model.Phone;
                        entityUpdate.Email = model.Email;

                        await _ctx.SaveChangesAsync();
                    }
                    _ctxTransaction.Commit();
                    message = "Entry Updated";
                }
                catch (Exception e)
                {
                    _ctxTransaction.Rollback(); e.ToString();
                    message = "Entry Update Failed!!";
                }

                result = new
                {
                    message
                };
            }
        }
        return result;
    }

    // DELETE api/Contact/DeleteContactByID/5
    [HttpDelete, Route("DeleteContactByID/{id}")]
    public async Task<object> DeleteContactByID(int id)
    {
        object result = null; string message = "";
        using (_ctx)
        {
            using (var _ctxTransaction = _ctx.Database.BeginTransaction())
            {
                try
                {
                    var idToRemove = _ctx.Contacts.SingleOrDefault(x => x.ContactId == id);
                    if (idToRemove != null)
                    {
                        _ctx.Contacts.Remove(idToRemove);
                        await _ctx.SaveChangesAsync();
                    }
                    _ctxTransaction.Commit();
                    message = "Deleted Successfully";
                }
                catch (Exception e)
                {
                    _ctxTransaction.Rollback(); e.ToString();
                    message = "Error on Deleting!!";
                }

                result = new
                {
                    message
                };
            }
        }
        return result;
    }
}

We can disable CORS by using attribute "DisableCors". In this controller, we have applied on "PUT" method to disable CORS.

Publishing to IIS

We need to prepare our Server for ASP.NET Core application to host. Get more details on Publish .NET Core Application. We have used localhost with assigning port 8081 to get access by our Sharing application. http://localhost:8081

cors27

Let's browse our application by using http://localhost:8081 url, as you can see, our API is working with response of JSON data.

core_23

Now, time to access the shared resource. I have added an existing sample application to this solution. Below is the simple change that I have made to access the resource via API from different origin.

Share Resource

JavaScript
public _saveUrl: string = 'http://localhost:8081/api/Contact/PostContact';
public _updateUrl: string = 'http://localhost:8081/api/Contact/PutContact';
public _getUrl: string = 'http://localhost:8081/api/Contact/GetContact';
public _getByIdUrl: string = 'http://localhost:8081/api/Contact/GetContactByID';
public _deleteByIdUrl: string = 'http://localhost:8081/api/Contact/DeleteContactByID';

Here, we have tried to access the resource through http://localhost:8081 but server error occurred, as you can see below.

core_25

After enabling CORS, we were successfully able to access the shared resource through Web API.

cors28

Output

core_24

Source Code: I’ve uploaded the full source code to download/clone @github, Hope this will help. :)

License

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


Written By
Software Developer (Senior) s3 Innovate Pte Ltd
Bangladesh Bangladesh
Hi, I am Shashangka Shekhar,

Working with Microsoft Technologies. Since March 2011, it was my first step to working with Microsoft Technologies, achieved bachelor’s degree on Computer Science from State University of Bangladesh(Dhaka). Have 12+ years of professional experience, currently working as Technical Lead at Surbana Jurong Private Limited.

I believe in desire of learning & also love to be a part of .Net Community by sharing knowledge’s.

Comments and Discussions

 
QuestionNot working Pin
subinms10-Mar-18 18:37
subinms10-Mar-18 18:37 

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.