1

私はJavascriptの次のビットを持っています:

 $.ajax({
    url: "/Web/WebServices/Operation.svc/SetScope",
    type: "POST",
    contentType: "application/json; charset=utf-8",
    beforeSend: function () {
    },
    dataType: "json",
    cache: false,
    data: JSON.stringify({
        Id: Id,
        RIds: RIds,
        rScope: rScope 
    }),
    success: function (data) { onSuccess(data); },
    error: function (data) { onError(data); }
    });

データビットを見ると -

  • ID は int です
  • RIds は int の配列です
  • rScope は、それぞれが int と string を含むオブジェクトの配列です

結果として

data: JSON.stringify({
            Id: Id,
            RIds: RIds,
            rScope: rScope 
        })

'{"Id":1,"rIds":[1,2,3,4],"rScope":[{"id":3,"type":"barney"},{"id":2, "タイプ":"テッド"}]}'

に渡すと$.parseJSON、期待されるオブジェクトが返されます。

問題は、400 Bad Request を返すことです。

呼び出しを待っている署名は、IIS でホストされている WCF にあります

public OperationResult SetScope(int rId, string rIds, string rScope)

コードから rScope を削除すると、すべて問題ありませんが、プリミティブだけではなく、オブジェクトが取り込まれた配列に問題があるようです。

ここで何が欠けていますか?

同様の質問が見つかりましたが、私のシナリオを実際に説明するものはありませんでした。

4

2 に答える 2

1

私が間違っていなければ、解析の結果は、単なる文字列ではなく、各オブジェクトがプロパティとプロパティをrScope持つオブジェクト配列であることを意味します。idtype

"rScope":[{"id":3,"type":"barney"},{"id":2,"nodetype":"ted"}]

これに似たクラスがある場合:

public class ScopeClass{
    public int Id {get; set;}
    public string Type {get; set;}
}

そして、次のようにメソッドで使用します。

public OperationResult SetScope(int rId, string rIds, IList<ScopeClass> rScope)

編集

nodetype実は、タイプの代わりに名前が付けられた 2 番目のオブジェクトもあることに気付きました。

上記のアプローチを使用する場合、渡すデータで nodetype も名前付きのタイプであることを確認する必要があります。そうしないと、値を一致させることができません。

また、プロパティ名を使用するTypeことは、C# のType. 影響力がある場合は、それが表すものなどType、より意味のあるものに更新しGroupType、渡されたデータで同じ名前を付けることができます。モデル バインダーは、単純にマジック マッチする必要があります。

于 2012-11-26T23:48:34.213 に答える
1

操作はrIdsパラメーターの文字列を想定していますが、配列を渡しています。自動的に行われる変換がいくつかありますが、非常に単純なもの (数値から文字列への変換など) のみです。また、rScope は文字列を想定していますが、オブジェクトを渡しています。

できることがいくつかあります。1 つ目は、データを「通常の」型ではなく文字列として渡すことです。これは、RIdsrScopeパラメータの両方を文字列化することを意味します。

var data = JSON.stringify({
    Id: Id,
    rIds: JSON.stringify(RIds),
    rScope: JSON.stringify(rScope)
});
$.ajax({
   url: "/Web/WebServices/Operation.svc/SetScope",
   type: "POST",
   contentType: "application/json; charset=utf-8",
   beforeSend: function () { },
   dataType: "json",
   cache: false,
   data: data,
   success: function (data) { onSuccess(data); },
   error: function (data) { onError(data); }
});

別の選択肢は、François Wahl が言及したものと一致し、送信しているデータを受け取る型を作成することです。rIdsパラメータとrScopeパラメータの両方に対してこれを行う必要があります。

public class StackOverflow_13575100
{
    [ServiceContract]
    public class Service
    {
        [WebInvoke(BodyStyle = WebMessageBodyStyle.Wrapped)]
        public string SetScope(int rId, string rIds, string rScope)
        {
            return string.Format("{0} - {1} - {2}", rId, rIds, rScope);
        }
        [WebInvoke(BodyStyle = WebMessageBodyStyle.Wrapped, ResponseFormat = WebMessageFormat.Json)]
        public string SetScopeTyped(int rId, int[] rIds, ScopeClass[] rScope)
        {
            return string.Format("{0} - {1} - {2}",
                rId,
                "[" + string.Join(", ", rIds) + "]",
                "[" + string.Join(", ", rScope.Select(s => s.ToString())) + "]");
        }
    }
    [DataContract]
    public class ScopeClass
    {
        [DataMember(Name = "id")]
        public int Id { get; set; }
        [DataMember(Name = "type")]
        public string Type { get; set; }

        public override string ToString()
        {
            return string.Format("Scope[Id={0},Type={1}]", Id, Type);
        }
    }
    public static void Test()
    {
        string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
        WebServiceHost host = new WebServiceHost(typeof(Service), new Uri(baseAddress));
        host.Open();
        Console.WriteLine("Host opened");

        WebClient c = new WebClient();
        c.Headers[HttpRequestHeader.ContentType] = "application/json";
        string data = @"{""Id"":1,""rIds"":[1,2,3,4],""rScope"":[{""id"":3,""type"":""barney""},{""id"":2,""type"":""ted""}]}";
        Console.WriteLine(data);
        try
        {
            Console.WriteLine(c.UploadString(baseAddress + "/SetScope", data));
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
        }

        c.Headers[HttpRequestHeader.ContentType] = "application/json";
        Console.WriteLine(c.UploadString(baseAddress + "/SetScopeTyped", data));

        Console.Write("Press ENTER to close the host");
        Console.ReadLine();
        host.Close();
    }
}
于 2012-11-27T00:03:40.267 に答える