저녁 내내 고군분투하고 난 후에 마침내 이것을 작동하게했습니다. 디버깅 후 내가 겪고있는 문제는 클라이언트가 소위 프리 플라이트 옵션 요청을 보내 응용 프로그램이 제공된 원본, 메소드 및 헤더와 함께 게시 요청을 보낼 수 있는지 확인하는 것이 었습니다. Owin 또는 APIController를 사용하고 싶지 않았으므로 발굴을 시작하고 ActionFilterAttribute만으로 다음 솔루션을 생각해 냈습니다. 특히 "Access-Control-Allow-Headers"부분은 언급 된 헤더가 요청이 보낼 헤더와 일치해야하므로 매우 중요합니다.
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);
}
}
}
}
마지막으로 내 MVC 작업 방법은 다음과 같습니다. 프리 플라이트 요청이 실패하므로 옵션 HttpVerbs도 언급해야합니다.
[AcceptVerbs(HttpVerbs.Post | HttpVerbs.Options)]
[AllowCrossSiteJson]
public async Task<ActionResult> Create(MyModel model)
{
return Json(await DoSomething(model));
}