Après avoir lutté pendant toute une soirée, j'ai finalement réussi à le faire fonctionner. Après un débogage, j'ai trouvé que le problème que je rencontrais était que mon client envoyait une soi-disant demande d'options de contrôle en amont pour vérifier si l'application était autorisée à envoyer une demande de publication avec l'origine, les méthodes et les en-têtes fournis. Je ne voulais pas utiliser Owin ou un APIController, j'ai donc commencé à creuser et j'ai trouvé la solution suivante avec juste un ActionFilterAttribute. En particulier, la partie "Access-Control-Allow-Headers" est très importante, car les en-têtes mentionnés doivent correspondre aux en-têtes que votre demande enverra.
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);
}
}
}
}
Enfin, ma méthode d'action MVC ressemble à ceci. Il est important ici de mentionner également les options HttpVerbs, car sinon la demande de contrôle en amont échouera.
[AcceptVerbs(HttpVerbs.Post | HttpVerbs.Options)]
[AllowCrossSiteJson]
public async Task<ActionResult> Create(MyModel model)
{
return Json(await DoSomething(model));
}