2011-08-09 16 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)]