将复杂类型的数组传递给Web API方法

时间:2014-04-14 16:06:36

标签: asp.net-web-api

我刚开始使用Web API中的复杂类型。我创建了一个简单的类,默认格式化程序应该没有问题:

public class GridColumnArgs
{
    public GridColumnArgs() { }

    public int FieldID { get; set; }
    public bool Visible { get; set; }
}

并设置一个采用GridColumnArgs的Web API方法:

public void PutGridLevel(int gridLevelID, GridColumnArgs columnArgs)
{
    // my breakpoint is set here
}

在JavaScript中,做了一个简单的测试方法:

var columnArgs = { FieldID: 1, Visible: true };
myHelperLibrary.put({
    url: 'api/grid?gridLevelID=123',
    obj: columnArgs,
    done: function () { alert('ok!') },
    fail: function () { alert('no good!') }
});

完美无缺。点击断点,我在JavaScript对象文字上设置的属性很棒。

但是我需要传递这些GridColumnArgs对象的集合。因此,如果我这样改变我的Web API方法:

public void PutGridLevel(int gridLevelID, GridColumnArgs[] columnArgs)
{
    // my breakpoint is set here
}

并调整我的测试JavaScript:

var columnArgs = [
    { FieldID: 1, Visible: true },
    { FieldID: 2, Visible: false }
];

myHelperLibrary.put({
    url: 'api/grid?gridLevelID=123',
    obj: columnArgs,
    done: function () { alert('ok!') },
    fail: function () { alert('no good!') }
});

通话不起作用。路由工作 - 我点击了我的断点。但参数是一个空数组。

显然,默认格式化程序无法像使用单一复杂类型那样轻松地处理复杂类型的数组。

我已经阅读了一些引用编写自定义媒体格式化程序来解决此问题的答案和文章,但是接受默认媒体格式化程序已经知道如何工作的对象数组似乎很麻烦用......最快捷的方法是什么?

非常感谢你的帮助!

3 个答案:

答案 0 :(得分:1)

不确定这是否会有所帮助,但您可以尝试添加属性。

[JsonProperty("FieldID")]
public int FieldID { get; set; }

或更改

public void PutGridLevel(int gridLevelID, dynamic columnArgs)

消除可能的类型问题。它可能是'var'而不是动态类型或尝试'对象'不能完全重新调整,也无法检查VS atm。

答案 1 :(得分:1)

我找到了另一种在Web API中绑定复杂对象类型的方法。我定义了一个模型绑定器,我在其中以字符串形式读取请求主体,然后使用JSON.NET将其反序列化为所需的对象类型。它也可以用于映射复杂对象类型的数组。

我添加了一个模型绑定器,如下所示:

public class PollRequestModelBinder : IModelBinder
{
    public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
    {
        var body = actionContext.Request.Content.ReadAsStringAsync().Result;
        var pollRequest = JsonConvert.DeserializeObject<PollRequest>(body);
        bindingContext.Model = pollRequest;
        return true;
    }
}

然后我在Web API控制器中使用它如下:

    public async Task<PollResponse> Post(Guid instanceId, [ModelBinder(typeof(PollRequestModelBinder))]PollRequest request)
    {
       // api implementation  
    }

答案 2 :(得分:0)

我有一个工作解决方案,在参数中使用JObject并使用Json.NET来解析数组。我仍然能够使用默认功能来实际实例化对象,但这似乎仍然太多工作和脆弱(更不用说如果我想支持另一个PUT路由,我需要实现自己的重载,等等。非常感谢更多的答案。

客户端代码:

var columnArgs = [
    { FieldID: 1, Visible: true },
    { FieldID: 2, Visible: false }
];

myHelperLibrary.put({
    url: 'api/grid?gridLevelID=123',
    obj: { columns: columnArgs },
    done: function () { alert('ok!') },
    fail: function () { alert('no good!') }
});

在服务器上:

public void PutGridLevel(int gridLevelID, JObject json)
{
    var jprop = json.Properties().FirstOrDefault(p => p.Name.Equals("columns", StringComparison.OrdinalIgnoreCase));
    if (jprop == null)
        throw new ArgumentException("The parameter object must contain an array property called \"columns\".");
    var columns = jprop.Value.ToArray().Select(obj => obj.ToObject<GridColumnArgs>());

// etc...
}