2012-01-27 63 views
10

我正在建設一個果園CMS模塊,我正在Orchard 1.3.10網站上進行測試。該模塊顯示我的一個實體的詳細信息視圖,並且我有一個「我的收藏」按鈕,我想單擊它,並對控制器操作執行ajax發佈以將實體保存爲數據庫中的收藏夾。登錄時果園CMS Ajax防僞令牌

在我有以下代碼視圖:

<div style="padding: 10px;"> 
    <span data-id="@Model.Id" id="addFavorite" style="cursor: pointer;"> 
    [Add Favorite] 
    </span> 
</div> 

<script type="text/javascript"> 
    $("#addFavorite").click(function() { 
     alert("here we go..."); 
     $.ajax({ 
      type: "post", 
      dataType: "", 
      url: "/orchardlocal/mymodule/stuff/AddFavorite", 
      data: { id: $(this).data("id") }, 
      success: function (response) { 
       alert("it worked"); 
      } 
     }); 
    }); 
</script> 

我的控制器動作...

[HttpPost] 
public ActionResult AddFavorite(int id) 
{ 
    return View(); 
} 

當我運行而不被登錄到果園現場,這段代碼的帖子剛回精細。如果我登錄並單擊添加收藏夾,我會得到此例外...

未提供所需的防僞標記或無效。

System.Web.Mvc.HttpAntiForgeryException由用戶代碼未處理 消息=未提供所需的防僞令牌或者無效。 源= System.Web.WebPages 錯誤碼= -2147467259 WebEventCode = 0 堆棧跟蹤: 在System.Web.Helpers.AntiForgeryWorker.Validate(HttpContextBase上下文,字符串鹽) 在System.Web.Helpers.AntiForgery.Validate( HttpContextBase HttpContext的,字符串鹽) 在System.Web.Mvc.ValidateAntiForgeryTokenAttribute.OnAuthorization(AuthorizationContext> filterContext)用C 在Orchard.Mvc.AntiForgery.AntiForgeryAuthorizationFilter.OnAuthorization(AuthorizationContext filterContext):\代碼\ OrchardDev2 \ SRC \果園\的mvc \ AntiForgery \ AntiForgeryAuthorizationFilter.cs:line 37 at System.Web.Mvc.ControllerActionInvoker.InvokeAuthorizationFilters(ControllerContext controllerContext,IList`1 filters,ActionDescriptor a ctionDescriptor) 在System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext,字符串actionName) 的InnerException:

爲什麼登錄而不是當它區別對待的帖子?

我該如何提供一個反僞造令牌來避免這種情況?

感謝, 布賴恩

回答

23

默認情況下,ASP.NET MVC不支持生成原始防僞標記。幸運的是,Orchard爲此提供了一種擴展方法。

您可以簡單地改變你的Ajax調用的是:

$.ajax({ 
    type: "post", 
    dataType: "", 
    url: "/orchardlocal/mymodule/stuff/AddFavorite", 
    data: { 
     id: $(this).data("id") }, 
     __RequestVerificationToken: '@Html.AntiForgeryTokenValueOrchard()' 
    }, 
    success: function (response) { 
     alert("it worked"); 
    } 
}); 

這種技術是有用,因爲你不需要你的頁面上的存在形式。儘管此解決方案僅在JavaScript從Razor視圖呈現時纔有效。

還有一個解決方案,如果你從你的觀點,這是保存防僞標記從視圖中聲明的JavaScript變量裏面,然後從腳本使用一個單獨的腳本文件:

@using(Script.Head()) { 
<script type="text/javascript"> 
//<![CDATA[ 
    var antiForgeryToken = '@Html.AntiForgeryTokenValueOrchard()'; 
//]]> 
</script> 
} 

然後從腳本:

data: { 
    id: $(this).data("id") }, 
    __RequestVerificationToken: antiForgeryToken 
} 

如果沒有,那麼由達林提出的解決方案將是他正確的做法。

+0

Sebastien,我認爲__RequestVerificationToken應該位於數據{}內部,有一點錯誤,正確嗎?另外,當我將@ Html.AntiForgeryTokenValueOrchard()添加到javascript時,我在VS中看到一條扭曲的線條,表示「條件編譯已經關閉」。我讀過另一篇文章,指出這是一個Razor錯誤,但我應該這樣做...... @(Html.AntiForgeryTokenValueOrchard())。但是,當我這樣做時,我得到了JavaScript錯誤「語法錯誤4」。我還能在這裏錯過什麼?謝謝,布賴恩 – 2012-01-27 21:59:54

+0

我完成了答案,考慮到您的意見 – 2012-01-28 00:18:50

+0

塞巴斯蒂安,這很好的作品。謝謝! – 2012-01-28 04:51:31

3

我如何可以提供一個防僞造令牌來避免這種情況?

這將取決於包含防僞造令牌的隱藏字段位於頁面上的位置。例如:

$("#addFavorite").click(function() { 
    var token = $(':input[name="__RequestVerificationToken"]').val(); 
    $.ajax({ 
     type: "post", 
     dataType: "", 
     url: "/orchardlocal/mymodule/stuff/AddFavorite", 
     data: { 
      __RequestVerificationToken: token, 
      id: $(this).data("id") 
     }, 
     success: function (response) { 
      alert("it worked"); 
     } 
    }); 
});