Después de luchar durante toda una noche, finalmente conseguí que esto funcionara. Después de algunas depuraciones, encontré que el problema con el que me encontraba era que mi cliente estaba enviando una llamada solicitud de Opciones de verificación previa para verificar si la aplicación podía enviar una solicitud de publicación con el origen, los métodos y los encabezados provistos. No quería usar Owin o un APIController, así que comencé a cavar y se me ocurrió la siguiente solución con solo un ActionFilterAttribute. Especialmente la parte "Acceso-Control-Permitir-Encabezados" es muy importante, ya que los encabezados mencionados allí tienen que coincidir con los encabezados que enviará su solicitud.
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MyNamespace
{
public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
HttpRequest request = HttpContext.Current.Request;
HttpResponse response = HttpContext.Current.Response;
// check for preflight request
if (request.Headers.AllKeys.Contains("Origin") && request.HttpMethod == "OPTIONS")
{
response.AppendHeader("Access-Control-Allow-Origin", "*");
response.AppendHeader("Access-Control-Allow-Credentials", "true");
response.AppendHeader("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE");
response.AppendHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, X-RequestDigest, Cache-Control, Content-Type, Accept, Access-Control-Allow-Origin, Session, odata-version");
response.End();
}
else
{
HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
HttpContext.Current.Response.Cache.SetNoStore();
response.AppendHeader("Access-Control-Allow-Origin", "*");
response.AppendHeader("Access-Control-Allow-Credentials", "true");
if (request.HttpMethod == "POST")
{
response.AppendHeader("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE");
response.AppendHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, X-RequestDigest, Cache-Control, Content-Type, Accept, Access-Control-Allow-Origin, Session, odata-version");
}
base.OnActionExecuting(filterContext);
}
}
}
}
Finalmente, mi método de acción MVC se ve así. Importante aquí es mencionar también las Opciones HttpVerbs, porque de lo contrario la solicitud de verificación previa fallará.
[AcceptVerbs(HttpVerbs.Post | HttpVerbs.Options)]
[AllowCrossSiteJson]
public async Task<ActionResult> Create(MyModel model)
{
return Json(await DoSomething(model));
}