I solved this problem after not finding the solution on Stackoverflow, so I am sharing my problem here and the solution in an answer.
After enabling a cross domain p
I wanted to allow this for a single method, not using a middleware to allow this on any method. This is what I ended doing:
[HttpOptions("/find")]
public IActionResult FindOptions()
{
Response.Headers.Add("Access-Control-Allow-Origin", new[] { (string)Request.Headers["Origin"] });
Response.Headers.Add("Access-Control-Allow-Headers", new[] { "Origin, X-Requested-With, Content-Type, Accept" });
Response.Headers.Add("Access-Control-Allow-Methods", new[] { "POST, OPTIONS" }); // new[] { "GET, POST, PUT, DELETE, OPTIONS" }
Response.Headers.Add("Access-Control-Allow-Credentials", new[] { "true" });
return NoContent();
}
[HttpPost("/find")]
public async Task<IActionResult> FindOptions([FromForm]Find_POSTModel model)
{
AllowCrossOrigin();
// your code...
}
private void AllowCrossOrigin()
{
Uri origin = null;
Uri.TryCreate(Request.Headers["Origin"].FirstOrDefault(), UriKind.Absolute, out origin);
if (origin != null && IsOriginAllowed(origin))
Response.Headers.Add("Access-Control-Allow-Origin", $"{origin.Scheme}://{origin.Host}");
}
And of course, you can implement IsOriginAllowed
as you wish
private bool IsOriginAllowed(Uri origin)
{
const string myDomain = "mydomain.com";
const string[] allowedDomains = new []{ "example.com", "sub.example.com" };
return
allowedDomains.Contains(origin.Host)
|| origin.Host.EndsWith($".{myDomain}");
}
You can find more details on how to enable CORS for POST requests on a single endpoint
welcome .
[HttpOptions("/find")] public IActionResult FindOptions()
{
Response.Headers.Add("Access-Control-Allow-Origin", new[] { (string)Request.Headers["Origin"] });
Response.Headers.Add("Access-Control-Allow-Headers", new[] { "Origin, X-Requested-With, Content-Type, Accept" });
Response.Headers.Add("Access-Control-Allow-Methods", new[] { "POST, OPTIONS" }); // new[] { "GET, POST, PUT, DELETE, OPTIONS" }
Response.Headers.Add("Access-Control-Allow-Credentials", new[] { "true" });
return NoContent();
}`enter code here`
This worked for me:
Make sure that this:
app.UseCors(builder => {
builder.AllowAnyOrigin();
builder.AllowAnyMethod();
builder.AllowAnyHeader();
});
Occurs before any of these:
app.UseHttpsRedirection();
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseCookiePolicy();
Remember, we are dealing with a "pipeline". The cors stuff has to be first.
-gimzani
There is no need in an additional middleware. As already mentioned above the only thing needed is the OPTIONS method allowed in Cors configuration. You may AllowAnyMethod as suggested here: https://stackoverflow.com/a/55764660/11921910
But it's safer to just allow the specific stuff like this:
app.UseCors(builder => builder
.WithOrigins("https://localhost", "https://production.company.com") /* list of environments that will access this api */
.WithMethods("GET", "OPTIONS") /* assuming your endpoint only supports GET */
.WithHeaders("Origin", "Authorization") /* headers apart of safe-list ones that you use */
);
Some headers are always allowed: https://developer.mozilla.org/en-US/docs/Glossary/CORS-safelisted_request_header
Add a middleware class to your project to handle the OPTIONS verb.
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Hosting;
namespace Web.Middlewares
{
public class OptionsMiddleware
{
private readonly RequestDelegate _next;
public OptionsMiddleware(RequestDelegate next)
{
_next = next;
}
public Task Invoke(HttpContext context)
{
return BeginInvoke(context);
}
private Task BeginInvoke(HttpContext context)
{
if (context.Request.Method == "OPTIONS")
{
context.Response.Headers.Add("Access-Control-Allow-Origin", new[] { (string)context.Request.Headers["Origin"] });
context.Response.Headers.Add("Access-Control-Allow-Headers", new[] { "Origin, X-Requested-With, Content-Type, Accept" });
context.Response.Headers.Add("Access-Control-Allow-Methods", new[] { "GET, POST, PUT, DELETE, OPTIONS" });
context.Response.Headers.Add("Access-Control-Allow-Credentials", new[] { "true" });
context.Response.StatusCode = 200;
return context.Response.WriteAsync("OK");
}
return _next.Invoke(context);
}
}
public static class OptionsMiddlewareExtensions
{
public static IApplicationBuilder UseOptions(this IApplicationBuilder builder)
{
return builder.UseMiddleware<OptionsMiddleware>();
}
}
}
Then add app.UseOptions();
this as the first line in Startup.cs in the Configure method.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseOptions();
}
I know it has been answered. Just answering with the updated information. So it would help others.
It is now built into the ASP.NET Core framework.
Just follow https://docs.microsoft.com/en-us/aspnet/core/security/cors
and replace
app.UseCors(builder =>
builder.WithOrigins("http://example.com"));
with
app.UseCors(builder =>
builder.WithOrigins("http://example.com")
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials());