7

それで、私はこれで壁に頭をぶつけてきました、そして私はこれのための良い情報源を見つけることができません。MVC3でモデルバインディングがどのように機能するかを忘れているかもしれませんが、これが私がやろうとしていることです。モデルの編集を処理するために、Knockoutにバインドされたエディターがあります。モデルにはあま​​りありません:

public class SetupTemplate
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Template { get; set; }
} 

私が呼び出そうとしているアクションのシグネチャは次のとおりです。

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult UpdateTemplate(SetupTemplate template)

ここでの別の質問から、偽造防止トークンを取得するために、このかなり役立つスニペットを選択しました。

window.addAntiForgeryToken = function(data) {
    data.__RequestVerificationToken = $('#__AjaxAntiForgeryForm input[name=__RequestVerificationToken]').val();
    return data;
};

これはすべて、ajaxを介して更新を投稿しようとしている私と一緒になります:

payload = window.addAntiForgeryToken(ko.mapping.toJS(self.data));
$.ajax({
    type: "post",
    url: endpoint,
    data: payload,
    success: function(data) {
        //Handle success
    }});

これにより、Chromeデベロッパーツールのフォームデータセクションが表示されます

Id:1
Name:Greeting
Template: [Template Text]
__RequestVerificationToken: [The really long anti-forgery token]

偽造防止トークンが取得されましたが、私のモデルはnullです。これについて私が見たほとんどの例では、モデルではなく、渡された単一のパラメーターを使用しています。

私は明らかな何かを見逃していると確信しています、それが何であるかについての洞察はありますか?

編集:@Markに応答して、呼び出しを次のように変更します。

$.ajax({
type: "post",
dataType: "json",
contentType: 'application/json',
url: endpoint,
data: JSON.stringify(payload),
success: function(data) {
    //Do some stuff
}});

結果は次のリクエストペイロードになります。

{"Id":1,"Name":"Greeting","Template":"...","__RequestVerificationToken":"..."}:

そして、サーバーは偽造防止トークンを取得していません。contentTypeこれは、へのパラメータがある場合とない場合の両方で試されました$.ajax()

4

5 に答える 5

2

同じ名前のプロパティの1つと衝突するため、マッピングはパラメーターをテンプレートとして使用できませんでした(大文字と小文字が区別されます)。テンプレート以外のものを使用する場合は、そのコントローラーパラメーターで適切に機能します。

詳細を説明するリンクがありますが、今では簡単に見つけることができません。

public class SetupTemplate
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Template { get; set; }
} 
于 2012-12-07T21:16:50.930 に答える
2

これが私の解決策です。次のようにjQuery関数を定義します。

(function ($) {
    $.getAntiForgeryToken = function () {
        return $('input[name="__RequestVerificationToken"]').val();
    };

    // (!) use ValidateJsonAntiForgeryToken attribute in your controller
    $.ajaxJsonAntiforgery = function (settings) {

        var headers = {};
        headers['__RequestVerificationToken'] = $.getAntiForgeryToken();

        settings.dataType = 'json';
        settings.contentType = 'application/json; charset=utf-8';
        settings.type = 'POST';
        settings.cache = false;
        settings.headers = headers;
        return $.ajax(settings);
    };
})(jQuery);

検証トークンをヘッダーに配置するだけです。偽造防止トークンを確認するには、フィルター属性も必要です。ここにあります:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Helpers;
using System.Web.Mvc;

namespace MyProject.Web.Infrastructure.Filters
{

    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class,
                    AllowMultiple = false, Inherited = true)]
    public sealed class ValidateJsonAntiForgeryTokenAttribute
                                : FilterAttribute, IAuthorizationFilter
    {
        public void OnAuthorization(AuthorizationContext filterContext)
        {
            if (filterContext == null)
            {
                throw new ArgumentNullException("filterContext");
            }

            var httpContext = filterContext.HttpContext;
            var cookie = httpContext.Request.Cookies[AntiForgeryConfig.CookieName];
            AntiForgery.Validate(cookie != null ? cookie.Value : null,
                                 httpContext.Request.Headers["__RequestVerificationToken"]);
        }
    }
}

コントローラでは、それは本当に簡単です。新しい属性(ValidateJsonAntiForgeryToken)でマークするだけです。

[Authorize, HttpPost, ValidateJsonAntiForgeryToken]
public ActionResult Index(MyViewModel viewModel)

そしてクライアント側では:

$.ajaxJsonAntiforgery({
    data: dataToSave,
    success: function() { alert("success"); },
    error: function () { alert("error"); }
});

わたしにはできる。楽しみ!

于 2013-11-19T11:32:35.983 に答える
1

使ってみJSON.stringifyませんか?

$.ajax({     
   type: "post",     
   url: endpoint,     
   data: JSON.stringify(payload),     
   success: function(data) {         
      //Handle success     
   } 
});
于 2012-08-30T11:32:05.277 に答える
1

@Markは、私をこの正しい道に導き、偽造防止トークンをかなり透過的に処理できるようになったいくつかのリンクを示したことで評価を得ています。ただし、問題を解決したのは次のとおりです。

public ActionResult UpdateTemplate(SetupTemplate template)

に:

public ActionResult UpdateTemplate(SetupTemplate model)

そして今、それは値を適切に埋めています。なぜそれが修正されたのか本当に知りたいのですが、今のところは機能します。

于 2012-08-30T14:40:10.530 に答える
0

実際、次のことが複雑なオブジェクトで機能しました。

var application = {
    Criteria: {
        ReferenceNumber: $("input[name='Criteria.ReferenceNumber'").val()
    },
    AppliedVia: "Office"
};

// get the next step
$.ajax({
    url: form.attr("action"),
    dataType: "html",
    type: "POST",
    data: {
        __RequestVerificationToken: $("input[name=__RequestVerificationToken]").val(),
        application: application
    },
}

ただし、注意すべき点の1つは、残さapplicationれたdataものがメソッド/アクションの実際のパラメーター名であることを確認することです。これはMVC5(.NET Coreより前)の時点で機能します

于 2016-08-17T12:57:19.910 に答える