2011-08-09 17 views
11

我的Sencha Touch应用程序正在向我的 WebService发布表单,但不是发送POST而是发送OPTIONS如何处理ASP.NET MVC中的“选项方法”

我正在读一个类似的线程here,但我只是不知道如何处理我的代码中的OPTIONS方法。

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

OPTIONS/GetInTouch/CommunicateCard HTTP/1.1
主机:webservice.example.com
的Referer:http://192.168.5.206/ 访问控制请求-方法: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-Contro 1-请求报头:X-请求-随着,内容类型
接受:/
接受编码:gzip,放气,SDCH
接受语言:EN-US,EN; Q = 0.8
接收字符集: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); 
    } 

回答

12

原来我不得不创建一个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); 
     } 
    } 
} 
+1

使用您发布的代码,我可以获得[Plupload](http:// http://www.plupload.com /)在各个网站上工作。我不知道为什么它在使用OPTIONS HTTP方法而不是POST之前保持不变,所以谢谢! –

+0

嗯,这不会返回正确的标题,以响应对我的选择请求:(... http://stackoverflow.com/questions/37216939/cors-requests-and-mvc5 – War

2

只是为了回答这个问题,为什么 “OPTIONS”,而不是 “POST”,那是因为浏览器正在实施CORS(Cross-origin resource sharing)。 这是一个发送OPTIONS请求的第一部分,然后如果服务器回复可接受的条件,浏览器然后发送数据/内容的实际请求。

4

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

实际上,您的代码希望忽略第一个CORS OPTIONS请求,因为这可能是“网站范围设置”,而不是每个API调用设置。

首先我配置IIS发送CORS响应,这可以通过IIS管理器(或通过网页。配置更新),如果你使用IIS然后去网站要添加这两个值:

  • 访问控制允许来源为“*”(用于测试,更大的安全性,您可能希望限制它某些主叫域)
  • 接入控制允许接头,

然后我创建的自定义ActionFilter,其具有被施加“内容类型,接受”(这是用于发布JSON数据)对于您希望接受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); 
     } 
    } 
} 

然后在每个控制器开始,你需要在属性应用此为加,如:

[CORSActionFilter] 
public class DataSourcesController : Controller 

现在我肯定是有办法做到这整个MVC解决方案(解决方案欢迎),但需要做一个烧烤和解决方案上面的作品!

+0

这里一个简短的文章,如何可以在web.config http://enable-cors.org/#how-iis7 – GibboK

4

添加以下到我的<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> 
+0

中设置好,除非它是全局的。接受的答案可以应用在“每个控制器”的基础上。 –

1

我在这里尝试了所有的答案,没有工作。我终于意识到,如果浏览器返回非200,那么浏览器会将它作为失败处理。在我的情况下,即使使用标题,IIS也会返回404。这是因为我的控制器方法有两个属性 - [HttpPost]和[HttpOptions]。显然,这不是表达多个动词的有效机制。我必须使用此属性来代替:[AcceptVerbs(HttpVerbs.Options | HttpVerbs.Post)]