c# - mvc - CORS en.NET Core
enable cors c# (5)
Estoy intentando habilitar CORS en .NET Core de esta manera:
public IConfigurationRoot Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options => options.AddPolicy("AllowAll", p => p.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()));
services.AddMvc();
}
public void Configure(IApplicationBuilder app)
{
app.UseCors("AllowAll");
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
Sin embargo, cuando estoy enviando una solicitud a mi aplicación con Angular 2 obtengo el famoso
"No hay encabezado ''Access-Control-Allow-Origin'' presente en el recurso solicitado".
mensaje de error.
También estoy usando Windows Authentication + WebListener. Si estoy consultando con el cartero, los únicos encabezados de respuesta son:
Content-Length → 3533 Content-Type → application / json; charset = utf-8 Fecha → Vie, 14 de octubre de 2016, 12:17:57 Servidor GMT → Microsoft-HTTPAPI / 2.0
Entonces debe haber algo mal configurado. ¿Alguna propuesta?
Si elimino la línea outcommented, funciona, pero necesito la autenticación de Windows :-(
var host = new WebHostBuilder()
.UseWebListener()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
//.UseWebListener(options => options.Listener.AuthenticationManager.AuthenticationSchemes = AuthenticationSchemes.NTLM)
.Build();
De esta manera funciona normalmente, solo lo intenté en angular2 con .net core. El problema que está teniendo el OP es que esto no funciona con la autenticación de Windows. Estoy asumiendo que el middleware para la autenticación de Windows está sucediendo antes de que se presente una solicitud, en cuyo caso se rompe. La mejor apuesta sería ver si hay una forma de habilitar el middleware de autenticación de Windows después de que el middleware de cors se haya procesado en Configure.
Entonces el orden sería
App.UseCors ()
App.UseWindowsAuth ()
App.UseMVC ()
Deben suceder en este orden para que funcione.
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options => options.AddPolicy("AllowAll", p => p.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()));
services.AddMvc();
}
public void Configure(IApplicationBuilder app)
{
app.UseCors("AllowAll");
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
En ASPNET CORE 2.0, lo siguiente funciona para mí
public void ConfigureServices(IServiceCollection services)
{
services.Configure<MvcOptions>(options =>
{
options.Filters.Add(new CorsAuthorizationFilterFactory("AllowSpecificOrigin"));
});
services.AddCors(options =>
{
options.AddPolicy("AllowSpecificOrigin",
builder => builder.WithOrigins("http://localhost:5000").AllowAnyHeader()
.AllowAnyMethod());
});
services.AddMvc()
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
loggerFactory.AddConsole();
loggerFactory.AddDebug(LogLevel.Information);
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
// Shows UseCors with named policy.
app.UseCors("AllowSpecificOrigin");
app.UseStaticFiles();
app.UseAuthentication();
app.UseMvcWithDefaultRoute();
}
}
La respuesta de @HockeyJ es correcta, pero puedes hacer algo más conciso si lo deseas.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
//Or if you want to chose what to include
services.AddMvcCore()
.AddCors()
(...)
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
//Cors
app.UseCors(builder =>
{
builder.AllowAnyHeader();
builder.AllowAnyMethod();
builder.AllowCredentials();
builder.AllowAnyOrigin(); // For anyone access.
//corsBuilder.WithOrigins("http://localhost:56573"); // for a specific url.
});
}
Lo que falta en la documentación es la importancia de .AllowAnyMethod (). Si no está presente, el temido No ''Acceso-Control-Permitir-Origen'' seguirá molestándote. En tu código está ahí, así que supongo que te perdiste configurar el encabezado correcto en la aplicación diaria del cliente.
Personalmente lo hice funcionar permitiendo todo:
app.UseCors(b => b.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin().AllowCredentials());
Y mi función de publicación angular como:
post(model) {
let headers = new Headers({
''Content-Type'':''application/json; charset=utf-8;''
,''Accept'':''*/*''
});
let options = new RequestOptions({ headers: headers });
let body = JSON.stringify(model);
return this.http.post(
''http://localhost:58847/api/TestPost'', body, options)
.map((response: Response) => {
let res = response.json();
return res;
}
);
}
Después de eso, poco a poco irás subiendo, especificando orígenes, etc.
Supongamos que tiene la respuesta, pero para el beneficio de los buscadores, tuve el mismo problema con el tutorial estándar sobre .NET Core Cors .
Uno de los muchos errores encontrados:
XMLHttpRequest no puede cargar localhost: 64633 / api / blogs. La respuesta a la solicitud de verificación previa no pasa la comprobación de control de acceso: No hay encabezado ''Access-Control-Allow-Origin'' presente en el recurso solicitado. El origen ''localhost: 56573'' no está, por lo tanto, permitido. La respuesta tenía código de estado HTTP 500.
Después de jugar, el siguiente código funcionó. Clase completa publicada a continuación para ayudar a comprender qué es lo que va.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Cors.Infrastructure;
namespace NetCoreWebApiTesting
{
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 framework services.
services.AddApplicationInsightsTelemetry(Configuration);
services.AddMvc().AddJsonOptions(options => options.SerializerSettings.ReferenceLoopHandling =
Newtonsoft.Json.ReferenceLoopHandling.Ignore);
// ********************
// Setup CORS
// ********************
var corsBuilder = new CorsPolicyBuilder();
corsBuilder.AllowAnyHeader();
corsBuilder.AllowAnyMethod();
corsBuilder.AllowAnyOrigin(); // For anyone access.
//corsBuilder.WithOrigins("http://localhost:56573"); // for a specific url. Don''t add a forward slash on the end!
corsBuilder.AllowCredentials();
services.AddCors(options =>
{
options.AddPolicy("SiteCorsPolicy", corsBuilder.Build());
});
}
// 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();
// ********************
// USE CORS - might not be required.
// ********************
app.UseCors("SiteCorsPolicy");
}
}
}
Para usarlo, puede agregar EnableCorsAttribute
en el controlador o en el método. p.ej
[EnableCors("SiteCorsPolicy")]
[Route("api/[controller]")]
public class BlogsController : Controller
{
}
o
// POST api/value
[EnableCors("SiteCorsPolicy")]
[HttpPost]
public HttpResponseMessage Post([FromBody]Blog value)
{
// Do something with the blog here....
var msg = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
return msg;
}
Cuando llamé esto usando el siguiente código (usando js / jQuery estándar para facilitar la copia y pegado), la comunicación dejó de ser rechazada.
function HandleClick() {
var entityData = {
"blogId": 2,
"url": "http://blog.com/blog1",
"posts": [
{
"postId": 3,
"title": "Post 1-1",
"content": "This is post 1 for blog 1",
"blogId": 2
},
{
"postId": 4,
"title": "Post 1-2",
"content": "This is post 2 for blog 1",
"blogId": 2
}
]
};
$.ajax({
type: "POST",
url: "http://localhost:64633/api/blogs",
async: true,
cache: false,
crossDomain: true,
data: JSON.stringify(entityData),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (responseData, textStatus, jqXHR) {
var value = responseData;
},
error: function (responseData, textStatus, errorThrown) {
alert(''POST failed.'');
}
});
}