So I have a view on a controller ...
[AllowAnonymous]
[Route("MyView")]
public ActionResult MyView()
{
// first attempt at solving problem
Response.AddHeader("Access-Control-Allow-Origin", "*");
Response.AddHeader("Access-Control-Allow-Headers", "*");
Response.AddHeader("Access-Control-Allow-Methods", "*");
return PartialView();
}
I tried adding this attribute (2nd attempt) ...
public class AllowCors : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Origin", "*");
filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Headers", "*");
filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Methods", "*");
base.OnActionExecuting(filterContext);
}
}
As im using owin to initialise my app I figured this might work (3rd attempt) ...
app.Use((context, next) =>
{
if (context.Request.Method == "OPTIONS")
{
context.Response.StatusCode = 200;
context.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
context.Response.Headers.Add("Access-Control-Allow-Headers", new[] { "*" });
context.Response.Headers.Add("Access-Control-Allow-Methods", new[] { "*" });
return context.Response.WriteAsync("handled");
}
return next.Invoke();
}).UseStageMarker(PipelineStage.PreHandlerExecute);
The problem is that if I just straight up ask for it by putting the url in the browser I get the right headers ...
Access-Control-Allow-Headers:*
Access-Control-Allow-Methods:*
Access-Control-Allow-Origin:*
... moving over in to postman to test this, when I issue an OPTIONS call to the same URL I get this in the headers ...
Allow: OPTIONS, TRACE, GET, HEAD, POST
... so how do I get MVC to respond correctly to the OPTIONS http verb so that I can use this view outside the domain of the site?
EDIT
it's worth noting that I have looked around already and found all these and many more ...
The requested resource does not support http method 'OPTIONS'.?
jQuery $.ajax(), $.post sending "OPTIONS" as REQUEST_METHOD in Firefox
AJAX in Chrome sending OPTIONS instead of GET/POST/PUT/DELETE?
Why does this jQuery AJAX PUT work in Chrome but not FF
How to support HTTP OPTIONS verb in ASP.NET MVC/WebAPI application
... i'm also very familiar with using CORS and making CORS requests in to WebAPI, but for some reason I can't seem to make a CORS request in to MVC without getting this seemingly "dummy" response back.
I think what I need is a means to override / replace the MVC default behaviour to this HttpVerb based request to allow me to embed views in a remote site.
Install these two nuget packages:
Microsoft.AspNet.Cors
Microsoft.Owin.Cors
Then in your Startup.cs add this line inside the Configuration function:
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
app.UseCors(CorsOptions.AllowAll);
}
}
In my demo setup I'm sending a post request from the domain http://example.local (Apache) to the domain http://localhost:6569/ (IIS Express).
Without app.UseCors(CorsOptions.AllowAll); (notice the warning in the console and no CORS headers):
And after adding the packages and adding the line to the Configuration method:
As you can see in the screenshot, the access-control-allow-origin was added in the response headers as expected/
Related
Making a post call to the API controller and no matter how to set things up, I get this response in the browser console.
Access to XMLHttpRequest at 'http://192.168.68.107:8090/api/Files/submitfile' from origin 'http://192.168.68.100:5173' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I have a .Net 6 Core API that I want to use in my local network. I have local IIS setup on a small server that I publish the API to. It deploys and mostly functions correctly. I have the CORS policy setup according to the docs.
var _policyName = "CorsPolicy";
builder.Services.AddCors(opt =>
{
opt.AddPolicy(name: _policyName, builder =>
{
builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod();
});
}
);
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors(_policyName);
app.UseAuthorization();
app.MapControllers();
app.Run();
API functions correctly when I launch Localhost and have my front end axios post call submit to it, but it will not work when I publish to the in house web server I have.
I've setup the axios call correctly. I believe I've setup the CORS policy correctly.
Only thing I can think of is the way I have the controller setup.
I have a controller that takes a FromBody parameter and it works perfectly Cross origin. It's here
[HttpPost, Route("new-category")]
public async Task<IActionResult> AddNewCategory([FromBody] CategoryDto category)
{
try
{
await _uploadService.SaveNewCategory(category.Category);
return Ok();
}
catch (Exception)
{
throw;
}
}
This controller is the culprit. No matter what I try CORS blocks this ..
[HttpPost, Route("submitfile")]
public async Task<IActionResult> SubmitFile([FromForm] FileUploadModel file)
{
try
{
if (file.File.Length <= 0)
return BadRequest("Empty File");
//save file
var fileLocation = await _uploadService.FileUpload(file.File, file.Category);
return Ok();
}
catch (Exception ex)
{
throw;
}
}
Here's the axios method that calls this controller.. which works when running localhost
await axios.post(API + "Files/submitfile", formData, {
headers: {
"Content-Type": "multipart/form-data",
},
The above CORS response is what I get. What am I missing here? How can I resolve this error?
Thank you for taking a look. Greatly appreciate the help
I don't know why that doesn't work, but I had a similar issue until I bypassed the named policy and applied the requirements in the UseCors() method:
app.UseCors(policy => {
policy.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin();
});
I am encountering a weird CORS issue when using C# ASP.NET Core 3.1 and GraphQL (Version="3.3.2"). In the Startup.cs file, I have setup the UseCors like this:
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
if (Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseCors (x => x
.AllowAnyOrigin ()
.AllowAnyMethod ()
.AllowAnyHeader ());
...
}
And also create a ConfigureCors function like this:
private void ConfigureCors(IServiceCollection services)
{
var requestOrigins = Configuration.GetSection("RequestOrigins")?
.GetChildren()
.Select(url => url.Value)
.ToArray() ?? new string[] {};
services.AddCors(options =>
{
options.AddPolicy(name: AllowSpecificOrigins,
builder =>
{
builder.WithOrigins(requestOrigins)
.AllowAnyHeader()
.AllowCredentials()
.AllowAnyMethod();
});
});
}
Called the ConfigureCors like this:
public void ConfigureServices(IServiceCollection services)
{
ConfigureCors(services);
...
}
In appsetting.{env}.json, I set the RequestOrigins:
"RequestOrigins": [
"http://localhost:8889"
]
When using frontend React to call the mutation like this:
const link = new HttpLink({
uri: 'https://localhost:5001/graphql/v1',
fetchOptions: {
credentials: 'include'
},
headers : {Authorization: `Bearer ${localStorage.getItem('Token')}`}
})
export default new ApolloClient({
link,
cache
});
It will throw the CORS issue:
Access to fetch at 'https://localhost:5001/graphql/v1' from origin 'http://localhost:8889' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.
However the backend log shows:
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
Request starting HTTP/1.1 OPTIONS https://localhost:5001/graphql/v1
info: Microsoft.AspNetCore.Cors.Infrastructure.CorsService[4]
CORS policy execution successful.
I am very confused:
Why are the OPTIONS not the POST, since I am calling a graphql mutation?
Why backend shows CORS policy execution successful, but frontend got CORS blocker?
However, if I commented out the Authentication part like this:
const link = new HttpLink({
uri: 'https://localhost:5001/graphql/v1',
//fetchOptions: {
//credentials: 'include'
//},
//headers : {Authorization: `Bearer ${localStorage.getItem('Token')}`}
})
Got the authorization failed error, but not CORS blocker. The token I have validated work in Postman. If I remove the app.UseCors, the CORS blocker comes back which is understandable. My guess is some CORS related configuration I didn't do right, but not sure which part, anyone knows what's going on? Thanks a lot!
based on Microsoft Doc's in this link when ever u add new policy u need to specify that policy to app.UseCors().
and also pay attention to this
The call to UseCors must be placed after UseRouting, but before UseAuthorization. For more information, see Middleware order.
Been attempting to integrate a React front-end with a .NET Framework backend and I am constantly coming into contact with CORS errors. The request I am sending to the server works on Postman. I extracted the code from Postman and put it into my react app (Fetch) and I receive the following error:
Access to fetch at 'http://localhost:33333/Token' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
However, on my .NET backend I added the following filter:
using System;
using System.Web.Mvc;
namespace TheFifth.Cors
{
public class AllowCrossSiteAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Origin",
"*");
filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Headers",
"*");
filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Credentials",
"true");
base.OnActionExecuting(filterContext);
}
}
}
Then referenced the Filter at the top of my Controller
[AllowCrossSite]
public class DA_Object
{
//some code
}
Does anyone know why my .NET backend or my React Frontend is preventing me from communicating across different ports - even though it works on Postman?
Additional Details
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/x-www-form-urlencoded");
var urlencoded = new URLSearchParams();
urlencoded.append("type", "x");
urlencoded.append("username", "x#x.com");
urlencoded.append("password", "x#");
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: urlencoded,
redirect: 'follow'
};
fetch("http://localhost:33333/api/Token", requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
In your startup.cs
in the ConfigureServices method you should have something like this, if you don't have then add it:
services.AddCors(options =>
{
options.AddPolicy(DefaultCorsPolicyName, builder =>
{
//App:CorsOrigins in appsettings.json can contain more than one address with splitted by comma.
builder
.AllowAnyOrigin()
.SetIsOriginAllowedToAllowWildcardSubdomains()
.AllowAnyHeader()
.AllowAnyMethod();
});
});
And in your appsettings.json add http://0.0.0.0:80 like this:
"App": {
...
"CorsOrigins": "http://*.mycompany.com,http://0.0.0.0:80",
...}
Another solution is to add a CORS extention in your browser and enable it, but it's not recommended
I'm trying to call my C# web-api from my Vue webapplication but I encounter the following error:
Access to XMLHttpRequest at 'http://www.api.example.com/'
from origin 'http://www.example.com' has been blocked by CORS policy:
Response to preflight request doesn't pass access control check:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
The following code snippet shows how I'm calling the rest-api with use of axios.
import axios from 'axios'
const client = axios.create({
baseURL: 'http://www.api.example.com',
json: true,
withCredentials: true
})
export default {
async execute(method, resource, data) {
return client({
method,
url: resource,
data,
headers: {}
}).then(req => {
return req
})
},
myFunc(data) {
return this.execute('post', '/', data)
}
}
The web-api with the POST request method is as follows:
[EnableCors("VueCorsPolicy")]
[Route("api/[controller]")]
[ApiController]
public class MyController : ControllerBase
{
[HttpPost]
public async Task<int> Post([FromBody] Data data)
{
// stuff
}
}
I have also added a CORS to my "ConfigureServices" method in the Startup.cs file.
services.AddCors(options =>
{
options.AddPolicy("VueCorsPolicy", builder =>
{
builder
.WithOrigins("http://www.example.com")
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
});
And lastly I have also added to the "Configure" method in the Startup.cs file:
app.UseCors("VueCorsPolicy");
CORS is a security mechanism, that cannot be overcome by simply modifying your code. The server has to be set so that it allows the requests from your source - so, if you control the server you can do it.
However, there are some solutions that help you during development phase, like cors-anywhere.herokuapp.com.
You should add it before the baseURL in your code, like this:
baseURL: 'https://cors-anywhere.herokuapp.com/http://www.api.example.com'.
This is NOT a solution for production, only for development.
You can host your own cors-anywhere app, more on this: https://www.npmjs.com/package/cors-anywhere
.WithOrigins("http://www.thomasleoblok.dk/") this is where your problem is, it should be .WithOrigins("http://www.example.com") since it is example.com you want to allow to make requests, it you want to allow any site you can change it to .WithOrigins("*")
if you are trying locally you must open the origin localhost, otherwise the BE will always return a cors error as localhost != http://www.thomasleoblok.dk/
for testing I suggest you enable AllowAnyOrigin()
example:
services.AddCors(options =>
{
options.AddPolicy("VueCorsPolicy", builder =>
{
builder
.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
});
I have problem consuming my OData with Breeze. My api is hosted on another server, and I'm using asp.net web api 2.0 (which comes with VS 2013 preview). I know web api is properly configured for CORS, because I've tested it without breeze, and it worked fine.
Here is web api 2.0 code which enables CORS:
var cors = new EnableCorsAttribute("http://localhost:7122/", "*", "*");
config.EnableCors(cors);
Here is my IEdmModel
private static IEdmModel CreateModel()
{
var modelBuilder = new ODataConventionModelBuilder {Namespace = "Test.Domain.Model"};
modelBuilder.EntitySet<MuscleGroup>("MuscleGroup");
modelBuilder.EntitySet<Exercise>("Exercises");
modelBuilder.EntitySet<ExerciseCategory>("ExerciseCategories");
modelBuilder.EntitySet<Muscle>("Muscle");
return modelBuilder.GetEdmModel();
}
Here is controller:
[EnableCors(origins: "http://localhost:7122", headers: "*", methods: "*")] //this enables CORS for controller
public class MuscleGroupController : EntitySetController<MuscleGroup, int>
{
private readonly DatabaseContext _databaseContext = new DatabaseContext();
[Queryable]
public override IQueryable<MuscleGroup> Get()
{
return _databaseContext.MuscleGroups;
}
protected override MuscleGroup GetEntityByKey(int key)
{
return _databaseContext.MuscleGroups.Find(key);
}
}
Here is how I consume OData using breeze:
app.adminMuscleGroup.dataService = ( function(breeze, logger) {
breeze.config.initializeAdapterInstances({ dataService: "OData" });
var servicename = "http://localhost:23758/odata/";
var manager = new breeze.EntityManager(servicename);
manager.enableSaveQueuing(true);
var dataService = {
getAll: getAll,
};
return dataService;
function getAll() {
var query = breeze.EntityQuery.from("MuscleGroup").orderBy("Name");
return manager.executeQuery(query);
}
And here is error I get:
Failed to load resource: the server responded with a status of 400 (Bad Request) http://localhost:23758/odata/$metadata
Failed to load resource: Origin http://localhost:7122 is not allowed by Access-Control-Allow-Origin. http://localhost:23758/odata/$metadata
XMLHttpRequest cannot load http://localhost:23758/odata/$metadata. Origin http://localhost:7122 is not allowed by Access-Control-Allow-Origin. MuscleGroup:1
[Q] Unhandled rejection reasons (should be empty):
Array[0]
q.js:891
Error: Metadata query failed for: http://localhost:23758/odata/$metadata; Logger.js:52
What I don't get is why url for query is: http://localhost:23758/odata/$metadata instead of http://localhost:23758/odata/$metadata#MuscleGroup
I know this answer explains how to use breeze with CORS, but I believe this was prior web api 2 and that I don't need to write class for CORS handling as I can do it now with:
var cors = new EnableCorsAttribute("http://localhost:7122/", "*", "*");
Long story short, my api handles CORS well (I've tested it) but for some reason it doesn't work with breeze.
EDIT
I've deleted this line [EnableCors(origins: "http://localhost:7122", headers: "*", methods: "*")] from controller, and just enabled CROS globbaly, but now I get this error:
[Q] Unhandled rejection reasons (should be empty):
Array[0]
q.js:891
Error: Metadata query failed for http://localhost:23758/odata/$metadata; Unable to process returned metadata: Cannot read property 'end' of null Logger.js:52
And I don't know what this property end is, as it isn't defined in my entities
var cors = new EnableCorsAttribute(
"http://localhost:7122/",
"*",
"*",
"DataServiceVersion, MaxDataServiceVersion"
);
config.EnableCors(cors);
Try adding DataServiceVersion and MaxDataServiceVersion to your EnableCorsAttribute.
This worked for me. I found it here.