How to use api with proxy url in Asp.Net for CORS
Making a Secure CORS Request in an ASP.NET MVC Controller
In modern web development, it's common to interact with external APIs or services to retrieve data for your application. However, when your web application runs in a browser and makes requests to a different domain or origin, you may encounter Cross-Origin Resource Sharing (CORS) restrictions. CORS is a security feature implemented by browsers to protect users from unauthorized cross-origin requests.
Scenario
Imagine you have an ASP.NET MVC application, and you need to fetch data from the "NPI Registry" API, which is hosted at https://npiregistry.cms.hhs.gov/RegistryBack/search
. The challenge is that the API server enforces strict CORS policies, allowing requests only from a specific origin, such as http://localhost:4200
. Our goal is to make a secure request from our ASP.NET MVC Controller to this external API.
The ASP.NET MVC Controller Action
Here's the code for our ASP.NET MVC Controller action that makes the secure CORS request:
public async Task GetSearchData(SearchCriteria data)
{
// Define the API URL
string apiURL = "https://npiregistry.cms.hhs.gov/RegistryBack/search";
// Define proxy settings for bypassing CORS restrictions
string MyProxyHostaddress = "localhost";
int MyProxyPort = 4200;
// Bypass SSL certificate verification (for demonstration purposes only)
ServicePointManager.ServerCertificateValidationCallback +=
delegate (object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors) { return true; };
// Create an HTTP request to the API
var request = (HttpWebRequest)WebRequest.Create(apiURL);
request.Proxy = new WebProxy(MyProxyHostaddress, MyProxyPort);
request.Method = "POST";
request.ContentType = "application/json";
request.Accept = "application/json";
// Serialize the data to JSON
string json = JsonConvert.SerializeObject(data);
// Create an HTTP client
var client = new HttpClient();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// Prepare the request content
var content = new StringContent(json, Encoding.UTF8, "application/json");
// Send the POST request to the API
var response = await client.PostAsync(apiURL, content);
// Read the response content as a string
string result = response.Content.ReadAsStringAsync().Result;
// Return the JSON result to the client
return Json(result);
}
Explaining the Code
1. Defining the API URL
// Define the API URL
string apiURL = "https://npiregistry.cms.hhs.gov/RegistryBack/search";
We start by defining the URL of the external API that we want to access.
2. Proxy Settings
// Define proxy settings for bypassing CORS restrictions
string MyProxyHostaddress = "localhost";
int MyProxyPort = 4200;
Because the API enforces strict CORS policies, we set up a proxy to bypass these restrictions. In this example, we specify the proxy host address and port.
3. Bypassing SSL Certificate Verification
// Bypass SSL certificate verification (for demonstration purposes only)
ServicePointManager.ServerCertificateValidationCallback +=
delegate (object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors) { return true; };
For demonstration purposes only, we bypass SSL certificate validation. In a production environment, you should not bypass certificate validation.
4. Creating the HTTP Request
// Create an HTTP request to the API
var request = (HttpWebRequest)WebRequest.Create(apiURL);
request.Proxy = new WebProxy(MyProxyHostaddress, MyProxyPort);
request.Method = "POST";
request.ContentType = "application/json";
request.Accept = "application/json";
We create an HttpWebRequest
object and configure it for a POST request to the API. We set the request headers, including Content-Type
and Accept
.
5. Serializing Data to JSON
// Serialize the data to JSON
string json = JsonConvert.SerializeObject(data);
We serialize the SearchCriteria
object to JSON because the API expects data in JSON format.
6. Creating an HTTP Client
// Create an HTTP client
var client = new HttpClient();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
We create an HttpClient
object to send the HTTP request.
7. Sending the Request
// Prepare the request content
var content = new StringContent(json, Encoding.UTF8, "application/json");
// Send the POST request to the API
var response = await client.PostAsync(apiURL, content);
We prepare the request content and send the POST request to the API.
8. Reading and Returning the Response
// Read the response content as a string
string result = response.Content.ReadAsStringAsync().Result;
// Return the JSON result to the client
return Json(result);
We read the response content as a string and return it as JSON to the client.
public class SearchCriteria { public string addressType { get; set; } public string aoFirstName { get; set; } public string aoLastName { get; set; } public string city { get; set; } public string country { get; set; } public string enumerationType { get; set; } public bool exactMatch { get; set; } public string firstName { get; set; } public string lastName { get; set; } public string organizationName { get; set; } public int? postalCode { get; set; } public int skip { get; set; } public string state { get; set; } public string taxonomyDescription { get; set; } }
Add this class to create the search object needed for api.
9 . Call api from View
@{ ViewBag.Title = "Home Page"; } <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script> <link rel="stylesheet" href="//cdn.datatables.net/1.10.24/css/jquery.dataTables.min.css"> <script src="//cdn.datatables.net/1.10.24/js/jquery.dataTables.min.js"></script> <div class="row"> <div class="col-md-12" style="margin-top:20px;margin-bottom:20px"> <div class="col-md-3">First Name</div> <div class="col-md-6"><input type="text" id="firstname" value="Brett" class="form-control" /></div> </div> <div class="col-md-12" style="margin-top:20px;margin-bottom:20px"> <div class="col-md-3"><input type="button" id="btnFilter" value="Search" onclick="Search()" /> </div> <div class="col-md-6"></div> </div> <br /> <br /> <div id="data"></div> </div> <script> var table; function Search() { var dataObj = { addressType: null, aoFirstName: null, aoLastName: null, city: null, country: null, enumerationType: null, exactMatch: false, firstName: $('#firstname').val() == "" ? null : $('#firstname').val(), lastName: null, //number: '', organizationName: null, postalCode: null, skip: 0, state: null, taxonomyDescription: null }; $.post('/Home/GetSearchData', dataObj, function (result) { console.log(result); $('#data').html(result); }) } </script>
Conclusion
In this article, we've explored how to make a secure CORS request from an ASP.NET MVC Controller to an external API. We've demonstrated how to set up a proxy to bypass CORS restrictions and explained the key steps involved in making the request. Remember to use this approach responsibly and securely in production environments and to follow best practices for handling external API requests in your applications. So this is how to use api with proxy url in Asp.Net application. This will also resolve the issue Access to XMLHttpRequest at 'https://npiregistry.cms.hhs.gov/RegistryBack/search' from origin 'https://localhost:44364' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The 'Access-Control-Allow-Origin' header has a value 'http://localhost:4200' that is not equal to the supplied origin.