(CORS C# ASP.NET Core) How Cross Origin requests (CORS) fail - example with ajax javascript

We shall run two ASPNET Core apps concurrently - the first exposes a web API, whereas the other shows a web page containing two links - the first of these links causes a direct call to the web API, and the second fires an ajax based call through javascript. A direct call is not a cross-origin (CORS) call because its destination is visible in the browser, but a call that occurs through an invocation of XMLHttpRequest or fetch API is a cross-origin (CORS) call. We shall verify that a click on the first link succeeds, but the second link fails because a browser blocks cross-origin calls.
(Rev. 19-Mar-2024)

Categories | About |     |  

Parveen,

Same Origin vs Cross Origin Urls

Let's first have a look at the terms same origin and cross origin.

Two addresses are considered as same origin addresses if they have the same schemes - for example, either both are of http type or both are https; and if they have the same host and their port numbers also match.

Following are examples of cross site addresses:

  1. http://google.com and https://google.com are cross site because their schemes differ.
  2. https://google.com and https://youtube.google.com are cross site because subdomains differ.
  3. https://google.com:1443 and https://google.com:1440 are cross site because ports differ.

Video Explanation (see it happen!)

Please watch the following youtube video:

Examples of Disabled Cross-Origin Requests

Now we'll look at the various types of cross-origin requests that browsers do not allow. For more detail please refer to the mozilla documentation website.

  1. Ajax calls through XMLHttpRequest and the Fetch API. These calls are considered hidden; they can execute without a user being aware of them and without his permission.
  2. Use of src property in @fontface in CSS. This allows websites to prevent other websites from linking to their fonts like a public CDN. Please note that nothing prevents others from downloading these resources by making direct hits.
  3. WebGL textures.
  4. Images and Videos rendered on a canvas by using the drawImage function.
  5. Use of url in properties like shape-outside.

Cross-Origin Projects - the first Project

We have created two projects - and both of them have been attached as downloads. Let's see them one by one!

The first project hosts a web api. Open the solution explorer, and locate the launchSettings.json file. This file sets the server port through the launchUrl and applicationUrl properties.


// launchsettings.json  
// sets the port number of the first app 

{
  "profiles": {
    "MyRazorApp": {
      "commandName": "Project",
      "launchBrowser": true,
      "launchUrl": "https://localhost:7276",
      "applicationUrl": "https://localhost:7276"
    }
  }
}

Next locate the Program.cs file. Double click to open it! This file contains the bare minimum code for launching an aspnet core listener.


// program.cs file of the first project 

// web api that will be called from the  
// second project 

var builder = WebApplication.CreateBuilder();

builder.Services.AddRazorPages();

var app = builder.Build();

app.MapRazorPages();

app.MapGet("/check", () => "hello api");

app.Run();

The MapGet extension adds a GET type of web api that responds with a string message. This is the API that we shall be calling from the second project.

Cross-Origin Projects - the second Project

Next, open the solution explorer of the second project and locate the launchSettings.json file. Double click to open it! The port has been set to a different value so that both the applications can run concurrently.


// launchSettings.json 
// sets the port number 

{
  "profiles": {
    "MyRazorApp": {
      "commandName": "Project",
      "launchBrowser": true,
      "launchUrl": "https://localhost:7277",
      "applicationUrl": "https://localhost:7277"
    }
  }
}

Again open the solution explorer and locate the program.cs file. Double click to open it!

As you can see, this file contains the usual lines to start a simple aspnet core application.


// program.cs 

var builder = WebApplication.CreateBuilder();

builder.Services.AddRazorPages();

var app = builder.Build();

app.MapRazorPages();

app.Run();

Next, locate the index.cshtml home page file and open it!


// file is index.cshtml.cs 
// contains two links - first for a direct call 
// second - for an ajax call 

@page

<h1>Welcome Home!</h1>

<a href="https://localhost:7276/check">Click to Call Directly</a> 

<a id="myButton" href="javascript:null">Click to Send Ajax Request</a>

<script type="text/javascript">

  myButton.onclick = function() {

      fetch("https://localhost:7276/check")
      .then((response) => response.text())
      .then((data) => alert(data))
      .catch((error) => { alert('Error:' + error); });

    }

</script>

First we have the @page directive, and then we have an anchor link to make a direct call to the web api.

After that we have a second anchor link that is connected to a javascript function. This function uses the fetch api to call the web api exposed by the first project. The response from the server is shown in an alert messagebox.

Run the Projects

Let's run and test the projects now.

First run the web api project and allow the home page to open. This project is now listening for requests.

Now run the second project also, and allow the home page to open. This page shows two links - the first link is for a direct call to the web api. Click the link! We observe that the call succeeds. A direct call is not a cross-origin (CORS) call because its destination is visible in the browser.

Again open the home page, and now let us try to make the ajax call. Such calls are classified as cross-origin calls. We observe that this call fails because the browser blocks cross origin calls.

Thus, we have seen how a cross origin call is blocked. Thanks!


This Blog Post/Article "(CORS C# ASP.NET Core) How Cross Origin requests (CORS) fail - example with ajax javascript" by Parveen is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.