17

ASP.NET MVCを使用して jQuery から JSON を投稿し、次の小さなライブラリ関数を使用して JSON を取得します。

(function($) {
    $.postJson = function(url, data) {
        return $.ajax({
            url: url,

            data: JSON.stringify(data),
            type: 'POST',
            dataType: 'json',
            contentType: 'application/json; charset=utf-8'
        });
    };
})(jQuery);

だから明らかに私はこれを次のように呼びます:

$('#button').click(function() {
    $.postJson('/controller/action', { Prop1: 'hi', Prop2: 'bye' })
    .done(function(r) { alert('It worked.'); })
    .fail(function(x) { alert('Fail! ' + x.status); });
});

ASP.NET MVC 3 と ASP.NET MVC 4 は、サブミット側をサポートします (その前に、JSON のサブミットを処理するために ASP.NET MVC を拡張する必要がありました) が、私が遭遇した問題は返ってきました。コントローラーでは、基本的に「成功、他に言うことは何もない」と言うために null を返すことがよくあります。

[HttpPost]
public JsonResult DoSomething(string Prop1, string Prop2)
{
    if (doSomething(Prop1, Prop2)
        return Json(null); // Success

    return Json(new { Message = "It didn't work for the following reasons" });
}

私はこのパターンを頻繁に使用していますが、正常に動作します。成功/完了のコールバックが呼び出され、すべてがうまくいきます。しかし最近、ASP.NET MVC と jQuery をアップグレードしたところ、機能しなくなりreturn Json(null);ました。さらに、応答を調べたところ、返された statusCode は実際には 200 であるため、サーバーは失敗していません。jQuery は失敗していると言っているだけです。

4

1 に答える 1

37

この問題は、jQuery 1.8 から 1.9 にアップグレードしたことが原因でした。jQuery 1.7 および 1.8 では、MVC で次のようになります。

return Json(null);

有効な JSON として受け入れられ、null として解釈されました。技術的には、これは空の文字列を HTTP 200 でクライアントに送り返しますが、jQuery <1.9 ではこれで十分です。

しかし、現在 (jQuery 1.9.1 を使用しています)、空の文字列を JSON として解析しようとします。jQuery の JSON パーサーは空の文字列に対して例外をスローし、fail()代わりにコールバックで終了するコード チェーンをトリガーします。

回避策は、代わりに、成功時に他の情報なしでサーバーからこれを返すことです。

return Json(new{});

これは、jQuery の JSON パーサーを使用したマスターに合格し、すべて順調です。これも機能します:

return Json(true);


アップデート

MVC によるこの動作は壊れているようです。ASP.NET MVC 3 でデフォルトの JSON シリアライザーとして JSON.NET を使用することに対するこの別のスタック オーバーフローの回答- 可能ですか? MVC が null を返すようにする方法について説明しますJson(null)。基本的には、ASP.NET MVC の組み込み JSON シリアライザーの代わりに Json.NET を使用します。これは、私が最終的に使用することになったソリューションです。

ただし、これを修正するには、その回答のわずかに変更されたバージョンを使用する必要があります-コードは以下にあります。基本的に、シリアル化に渡す前に null をチェックするステートメントを含めないでください。そうしないifと、同じ苦境に戻ってしまいます。


更新 2

Json.NET での ISO 8601 日付の既定の実装は、Internet Explorer 9以下で解析しようとすると中断しnew Date(...)ます。つまり、これらは Internet Explorer 9 で適切に解析されます。

var date = new Date('2014-09-18T17:21:57.669');
var date = new Date('2014-09-18T17:21:57.600');

しかし、これは例外をスローします:

var date = new Date('2014-09-18T17:21:57.6');

Internet Explorer 9 の Date() 実装は、正確に 3 ミリ秒の桁しか処理できません。これを修正するには、Json.NET の日付形式を強制的にオーバーライドする必要があります。以下のコードに含まれています。

public class JsonNetResult : JsonResult
{
    public override void ExecuteResult(ControllerContext context)
    {
        if (context == null)
            throw new ArgumentNullException("context");

        var response = context.HttpContext.Response;

        response.ContentType = !String.IsNullOrEmpty(ContentType) ? ContentType : "application/json";

        if (ContentEncoding != null)
            response.ContentEncoding = ContentEncoding;

        var settings = new JsonSerializerSettings
        {
            Converters = new[] {new IsoDateTimeConverter
            {
                DateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.fffK"
            }}
        };
        var jsonSerializer = JsonSerializer.Create(settings);

        jsonSerializer.Serialize(response.Output, Data);
    }
}

これを BaseController に結び付ける方法を示す Gist:

https://gist.github.com/b9chris/6991b341e89bb0a4e6d801d02dfd7730

于 2013-04-11T02:55:10.737 に答える