【问题标题】:WebApi Parameter is not null but has empty valuesWebApi 参数不为空但具有空值
【发布时间】:2014-02-15 00:02:30
【问题描述】:

这是添加了 [FromBody] 属性的默认 webapi 方法:

// PUT api/Pedidos/5
    public async Task<IHttpActionResult> PutPedido(Guid id,[FromBody]Job pedido)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        if (id != pedido.Id)
        {
            return BadRequest();
        }

        db.Entry(pedido).State = EntityState.Modified;

        try
        {
            await db.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!PedidoExists(id))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }

        return StatusCode(HttpStatusCode.NoContent);
    }

这是 jquery 请求:

self.update = function () {                
            $.ajax({
                type: "PUT",
                url: baseUri + '@Model.Id',
                data: ko.toJSON(updatableData),                    
                dataType: "json",
                contentType: "application/json"
            })
                .done(function (data) {

                    alert('Magic');
                })
                .error(function (jqXHR, textStatus, errorThrown) {
                    alert(errorThrown);
                    alert("fail");
                });
        }

这是数据:

var updatableData = {
            Id : '@Model.Id',
            Name : '@Model.Name',
            AbreviaNome: self.AbreviaNome(),
            AbreviaFantasia: self.AbreviaFantasia,
            AbreviaLogradouro: self.AbreviaLogradouro,
            AbreviaComplemento: self.AbreviaComplemento,
            AbreviaBairro: self.AbreviaBairro,
            AbreviaCidade: self.AbreviaCidade,
            AbreviaExtra: self.AbreviaExtra,
        };

这是部分 c# 模型,我删除了大约 7 个字段,其中 2 个是日期,其余是字符串:

public class Job
{       
    public Guid Id { get; set; } 
    [Required]   
    public string Name {get;set;}    
    public int TotalItems { get; set; }        
    public bool AbreviaNome { get; set; }
    public bool AbreviaFantasia { get; set; }
    public bool AbreviaLogradouro { get; set; }
    public bool AbreviaComplemento { get; set; }
    public bool AbreviaBairro { get; set; }
    public bool AbreviaCidade { get; set; }
    public bool AbreviaExtra { get; set; }
    public virtual ICollection<Item> Items { get; set; }        
}

我使用带有 knockout.js 的 ASP.NET,这就是为什么您在数据上看到“self”的原因。请求通过了,我可以很好地使用 PUT 方法。但是 pedido 实例具有所有错误值并且根本没有 Id(仅在第一个参数上),并且所有值都应该为真,除了最后一个,在我尝试时,请参阅请求正文内容:

{"Id":"c47f0ad2-0783-e311-8289-88532ee08d00", "Name":"Test 1","AbreviaNome":true,"AbreviaFantasia":true,"AbreviaLogradouro":true,"AbreviaComplemento":true,"AbreviaBairro":true,"AbreviaCidade":true,"AbreviaExtra":false}

这里可能会发生什么?我必须在“updatableData”对象上有所有字段吗?还有其他方法可以实现我的需要吗?

编辑: 我在模型中添加了一个字段,但它的重要“名称”是必填字段,并且在某处出现错误,它认为名称值不在请求中,而实际上在更正后。

编辑: 在 ModelBinding 中发现错误,与所需名称有关:

{"$id":"1","Message":"The request is invalid.","ModelState":{"$id":"2","pedido.Name":["The Name field is required."]}}

我从 Name 属性中删除了 [Required] 属性,然后它停止工作,更糟糕的是,在 ModelBinding 中我只得到一个参数,即 Id。 当我把 required 放回去时,它会恢复工作但出现上述错误。

【问题讨论】:

  • 你真的需要 [FromBody] 属性吗?只有标量参数才需要它。如果删除它会发生什么?
  • 您的代码应该可以工作,但是我看到一些奇怪的东西:在您的 $.ajax 中,contenttype 应该是 contentType Type 应该以大写字母 T 开头。
  • 我已经删除了属性并更正了 contentType 拼写(Nice Catch),但行为仍然相同......
  • 检查 Chrome Net 控制台并查看您收到的错误,然后在此处发布。
  • 试试Postman。这是一个 chrome 扩展,可让您“手动”发送请求。您可以使用它来确保电线中发生的事情没有任何问题。内容类型肯定是错误的,它是 contentType

标签: c# jquery asp.net knockout.js asp.net-web-api


【解决方案1】:

尝试使用JSON.stringify 而不是ko.ToJSON

self.update = function () {                
            $.ajax({
                type: "PUT",
                url: baseUri + '@Model.Id',
                data: JSON.stringify(updatableData),                    
                datatype: "json",
                contenttype: "application/json"
            })
                .done(function (data) {
                alert('Magic');
            })
            .error(function (jqXHR, textStatus, errorThrown) {
                alert(errorThrown);
                alert("fail");
            });
    }

此外,您似乎传递了一个对象但需要 2 个参数,因此您不需要方法签名上的 Guid id,因为它已经在 Job 对象中:

public async Task<IHttpActionResult> PutPedido([FromBody]Job pedido)

【讨论】:

  • 他的方法是有效的,guid 将被加载隐式 FromURI 和复杂的 Object 显式 [FromBody]。但我怀疑他在浏览器控制台中发帖时出错。
  • Tanner,我确实尝试了 stringify 方法,它在 {"Id":"96ed3a0f-fb84-e311-8289-88532ee08d00","Name":"Test 2", "AbreviNome":true},它缺少所有其他的东西,它仍然没有工作。
  • 关于 2 个参数:我相信这是正确的方法,因为正确的 REST 实现会返回一个资源 URL(http:\\test.com\api\pedido\some-big-key),当您调用以将更改应用于该资源时,您将使用整个 URL,并将更改传递到正文中,就像 Floradu88 描述的那样。
猜你喜欢
  • 1970-01-01
  • 2021-12-19
  • 1970-01-01
  • 2016-09-06
  • 2018-12-24
  • 1970-01-01
  • 2023-03-27
  • 1970-01-01
  • 2019-09-30
相关资源
最近更新 更多