复杂类型在 ApiController 参数中为空

Posted

技术标签:

【中文标题】复杂类型在 ApiController 参数中为空【英文标题】:Complex type is getting null in a ApiController parameter 【发布时间】:2012-10-06 15:35:42 【问题描述】:

我不知道为什么我的参数“ParametroFiltro Filtro”为空,而其他参数“page”和“pageSize”却正常。

public class ParametroFiltro

    public string Codigo  get; set; 
    public string Descricao  get; set; 

我的 ApiController 获取方法:

public PagedDataModel<ParametroDTO> Get(ParametroFiltro Filtro, int page, int pageSize)

我的 ajax 调用:

var fullUrl = "/api/" + self.Api;
$.ajax(
    url: fullUrl,
    type: 'GET',
    dataType: 'json',
    data:  Filtro:  Codigo: '_1', Descricao: 'TESTE' , page: 1, pageSize: 10 ,
    success: function (result) 
        alert(result.Data.length);
        self.Parametros(result.Data);
    
);

【问题讨论】:

【参考方案1】:

您正在尝试使用GET 方法发送一个复杂对象。失败的原因是 GET 方法不能有正文,并且所有值都被编码到 URL 中。您可以使用[FromUri] 来完成这项工作,但首先您需要更改客户端代码:

$.ajax(
    url: fullUrl,
    type: 'GET',
    dataType: 'json',
    data:  Codigo: '_1', Descricao: 'TESTE', page: 1, pageSize: 10 ,
    success: function (result) 
        alert(result.Data.length);
        self.Parametros(result.Data);
    
);

如果您像这样更改您的操作方法,[FromUri] 将能够直接从 URL 中获取您的复杂对象属性:

public PagedDataModel<ParametroDTO> Get([FromUri]ParametroFiltro Filtro, int page, int pageSize)

您以前的方法宁愿使用可以有正文的POST 方法(但您仍然需要使用JSON.stringify() 将正文格式化为 JSON)。

【讨论】:

现在它已经奏效了,tks 很多。我浪费了整个上午试图解决它。 谢谢,工作就像一个魅力。 [FromUri] 就是我所需要的!奇怪的是它甚至明确需要它......我认为 Web API 会假设它在 Uri 中,因为它是 GET 再次感谢您。有趣的是,复杂对象的参数名称(在本例中为“Filtro”)不应在请求中传递 - 非常违反直觉。我想知道如果您有具有相同名称(或对象列表)字段的子对象会发生什么 - 大概它会抛出? 看起来你必须用 [FromUri] 来装饰每个复杂的参数。我试过装饰控制器无济于事(没有例外只是没有效果),这是一种耻辱。如果有人发现其他情况,请大声疾呼。 这对我不起作用,原始类型参数有效,但对象参数仍然为空。【参考方案2】:

在进行 ajax 调用时提供 contentType 属性。使用JSON.stringify 方法构建要发布的 JSON 数据。将类型更改为POST,MVC 模型绑定会将发布的数据绑定到您的类对象。

var filter =  "Filtro":  "Codigo": "_1", "Descricao": "TESTE" , 
                                               "page": "1", "pageSize": "10" ; 
$.ajax(
    url: fullUrl,
    type: 'POST',
    dataType: 'json',
    contentType: 'application/json',
    data: JSON.stringify(filter),
    success: function (result) 
        alert(result.Data.length);
        self.Parametros(result.Data);
    
);

【讨论】:

POST 请求将建议在后端修改某些实体/集合。【参考方案3】:

还可以通过Newtonsoft.Json.Linq JObject 访问 POST 变量。

例如,这个 POST:

$.ajax(
    type: 'POST',
    url: 'URL',
    data:  'Note': note, 'Story': story ,
    dataType: 'text',
    success: function (data)  
);

可以像这样在 APIController 中访问:

public void Update([FromBody]JObject data)

    var Note = (String)data["Note"];
    var Story = (String)data["Story"];

【讨论】:

我可以通过 GET 方法来实现吗?在我的场景中,我不需要Update,我需要基于一个假设的复杂对象及其所有属性集来Get【参考方案4】:

如果您将 json 数据附加到查询字符串,并稍后在 web api 端解析它。你也可以解析复杂的对象。它比发布 json 对象更有用,尤其是在一些特殊的 httpget 需求案例中。

//javascript file 
    var data =  UserID: "10", UserName: "Long", AppInstanceID: "100", ProcessGUID: "BF1CC2EB-D9BD-45FD-BF87-939DD8FF9071" ;
    var request = JSON.stringify(data);
    request = encodeURIComponent(request);

    doAjaxGet("/ProductWebApi/api/Workflow/StartProcess?data=", request, function (result) 
        window.console.log(result);
    );

    //webapi file:
    [HttpGet]
    public ResponseResult StartProcess()
    
        dynamic queryJson = ParseHttpGetJson(Request.RequestUri.Query);
            int appInstanceID = int.Parse(queryJson.AppInstanceID.Value);
        Guid processGUID = Guid.Parse(queryJson.ProcessGUID.Value);
        int userID = int.Parse(queryJson.UserID.Value);
        string userName = queryJson.UserName.Value;
    

    //utility function:
    public static dynamic ParseHttpGetJson(string query)
    
        if (!string.IsNullOrEmpty(query))
        
            try
            
                var json = query.Substring(7, query.Length - 7); //seperate ?data= characters
                json = System.Web.HttpUtility.UrlDecode(json);
                dynamic queryJson = JsonConvert.DeserializeObject<dynamic>(json);

                return queryJson;
            
            catch (System.Exception e)
            
                throw new ApplicationException("can't deserialize object as wrong string content!", e);
            
        
        else
        
            return null;
        
    

【讨论】:

以上是关于复杂类型在 ApiController 参数中为空的主要内容,如果未能解决你的问题,请参考以下文章

值不能为空。参数名称:routeCollection + ApiController

如何在 ApiController 中为单个方法返回 JSON?

参数值在 Ajax 中为空?

检查 DateTime 类型的值是不是在视图中为空,如果为空则显示空白

存储过程中为空时处理动态参数

express-graphql 解析器参数在解析器中为空,但 info variableValues 填充了名称和值