Asp.net web api 将复杂类型的数组传递给Web API方法

Asp.net web api 将复杂类型的数组传递给Web API方法,asp.net-web-api,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

我刚刚开始学习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!') }
});
电话不通。路由工作-我击中了我的断点。但是参数是一个空数组

因此,显然,默认格式化程序不能像处理单个复杂类型那样轻松地处理复杂类型的数组

我读过一些关于编写自定义媒体格式化程序来解决此问题的答案和文章,但要接受默认媒体格式化程序已经知道如何使用的对象数组,似乎有很多麻烦。。。最快的方法是什么


非常感谢你的帮助

不确定这是否有用,但您可以尝试添加属性

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

public void PutGridLevel(int gridLevelID, dynamic columnArgs)

以消除可能的类型问题。它可能使用“var”而不是动态类型,或者尝试使用“object”无法准确地重新调用,也无法从VS atm中进行检查。

我有一个工作解决方案,它在参数中使用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...
}
public void PutGridLevel(int-gridLevelID,JObject-json)
{
var jprop=json.Properties().FirstOrDefault(p=>p.Name.Equals(“columns”,StringComparison.OrdinalIgnoreCase));
if(jprop==null)
抛出新ArgumentException(“参数对象必须包含名为“columns”的数组属性”);
var columns=jprop.Value.ToArray().Select(obj=>obj.ToObject());
//等等。。。
}

我在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;
    }
}
    public async Task<PollResponse> Post(Guid instanceId, [ModelBinder(typeof(PollRequestModelBinder))]PollRequest request)
    {
       // api implementation  
    }
公共类PollRequestModelBinder:IModelBinder
{
public bool BindModel(HttpActionContext actionContext,ModelBindingContext bindingContext)
{
var body=actionContext.Request.Content.ReadAsStringAsync().Result;
var pollRequest=JsonConvert.DeserializeObject(主体);
bindingContext.Model=pollRequest;
返回true;
}
}
然后我在Web API控制器中使用它,如下所示:

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;
    }
}
    public async Task<PollResponse> Post(Guid instanceId, [ModelBinder(typeof(PollRequestModelBinder))]PollRequest request)
    {
       // api implementation  
    }
公共异步任务Post(Guid实例ID,[ModelBinder(typeof(PollRequestModelBinder))]PollRequest请求)
{
//api实现
}

当JSON属性的名称不同于C#属性时,
JsonPropertyAttribute
最有用。默认情况下,它使用C#属性名称进行映射。感谢LIUFA的想法,但这并没有解决问题。我尝试了您的第二个建议,将参数更改为dynamic。到达的参数是一个“对象”,但我似乎无法对其执行任何操作-不强制转换为ExpandooObject、Array或IEnumerable,没有长度或计数属性。请尝试将其添加到VS中的“监视”或在“即时窗口”中对其执行操作,以查看该对象是什么,这可能会给您一些想法。