如何处理ASP.NET MVC中的"OPTIONS方法"

Cha*_*ell 14 ajax asp.net-mvc-3 http-options-method

我的Sencha Touch应用程序正在将表单发布到我的 WebService,但不是发送POST它的发送OPTIONS.

我在这里读了一个类似的线程,但我不知道如何处理OPTIONS我的代码中的方法.

我确实尝试将[AllowAjax]属性添加到我的Action中,但它似乎不存在于MVC3中.

选项/ GetInTouch/CommunicateCard HTTP/1.1
主机:webservice.example.com
参考资料:http://192.168.5.206/ Access-Control-Request-Method:POST
来源:http://192.168.5.206
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0)AppleWebKit/534.24(KHTML,与Gecko一样)Chrome/11.0.696.71 Safari/534.24
Access-Control-Request-Headers:X-Requested-With,Content-Type
Accept:/
Accept-Encoding: gzip,deflate,sdch
Accept-Language:en-US,en; q = 0.8
Accept-Charset:ISO-8859-1,utf-8; q = 0.7,*; q = 0.3

在我的ActionMethod中,我使用以下代码.

    public JsonpResult CommunicateCard(CommunicateCard communicateCard)
    {

        // Instantiate a new instance of MailMessage
        MailMessage mMailMessage = new MailMessage();

        // removed for security/brevity

        // Set the body of the mail message
        mMailMessage.Body = communicateCard.name; // THIS IS CURRENTLY BLANK :-(

        // removed for security/brevity
        mSmtpClient.Send(mMailMessage);

        // do server side validation on form input
        // if it's valid return true
        // else return false
        // currently returning NULL cuz I don't care at this point.
        return this.Jsonp(null);
    }
Run Code Online (Sandbox Code Playgroud)

Cha*_*ell 13

事实证明我必须创建一个 ActionFilterAttribute

namespace WebService.Attributes
{
    public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
            HttpContext.Current.Response.Cache.SetNoStore();

            filterContext.RequestContext.HttpContext.Response.AppendHeader("Access-Control-Allow-Origin", "*");

            string rqstMethod = HttpContext.Current.Request.Headers["Access-Control-Request-Method"];
            if (rqstMethod == "OPTIONS" || rqstMethod == "POST")
            {
                filterContext.RequestContext.HttpContext.Response.AppendHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
                filterContext.RequestContext.HttpContext.Response.AppendHeader("Access-Control-Allow-Headers", "X-Requested-With, Accept, Access-Control-Allow-Origin, Content-Type");
            }
            base.OnActionExecuting(filterContext);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Fro*_*nia 8

我在MVC和IIS中以不同的方式解决了这个问题.我发现这个问题的原因是因为我想从客户端javascript(JSONP不起作用)POST数据,并且最重要的是希望允许JSON数据位于POST请求的内容中.

实际上,您的代码想要忽略第一个CORS OPTIONS请求,因为这可能是"站点范围设置",而不是每个API调用设置.

首先我配置IIS发送CORS响应,这可以通过IIS管理器(或通过web.config更新)完成,如果您使用IIS然后转到要添加这两个值的站点:

  • Access-Control-Allow-Origin为"*"(用于测试,为了更高的安全性,您可能希望将其限制为某些调用域)
  • Access-Control-Allow-Headers,"Content-Type,Accept"(这是用于发布JSON数据)

然后我创建了一个自定义ActionFilter,它必须应用于您想要接受POST数据的每个控制器,这可能会触发CORS请求.自定义操作筛选器是:

public class CORSActionFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (filterContext.HttpContext.Request.HttpMethod == "OPTIONS")
        {
            // do nothing let IIS deal with reply!
            filterContext.Result = new EmptyResult();
        }
        else
        {
            base.OnActionExecuting(filterContext);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在每个控制器的开头,你需要应用它来添加一个属性,例如:

[CORSActionFilter]
public class DataSourcesController : Controller
Run Code Online (Sandbox Code Playgroud)

现在我确信有一种方法可以在整个MVC解决方案中实现这一点(欢迎解决方案),但需要进行烧烤并且上面的解决方案有效!


小智 6

我在<system.webServer>配置部分添加了以下内容:

<httpProtocol>
  <customHeaders>
    <add name="Access-Control-Allow-Headers" value="Content-Type, Accept, X-Requested-With"/>
    <add name="Access-Control-Allow-Methods" value="GET, POST, OPTIONS"/>
    <add name="Access-Control-Allow-Origin" value="*"/>
  </customHeaders>
</httpProtocol>
Run Code Online (Sandbox Code Playgroud)