我有一个带PUT方法的控制器,它通过JSON接受一组参数,然后更新数据库。但是,PUT的默认行为似乎是如果缺少参数,则会将其恢复为null。
例如,代码:
// PUT: api/Business/5
[ResponseType(typeof(void))]
public async Task<IHttpActionResult> Putuser_business(int id, DTO_business_details dto_us_bus)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
//new code
var dto_bus_details = await db.user_business.Select(us_bus =>
new DTO_business_details()
{
BusinessID = id,
BusinessName = us_bus.bus_name,
Address = us_bus.bus_address,
PhoneNumber = us_bus.bus_phone
}).SingleOrDefaultAsync(us_bus=> us_bus.BusinessID == id);
dto_us_bus.BusinessID = dto_bus_details.BusinessID;
if (dto_us_bus.BusinessName == null) { dto_us_bus.BusinessName = dto_bus_details.BusinessName ; }
if (dto_us_bus.Address== null) { dto_us_bus.Address= dto_bus_details.Address; }
if (dto_us_bus.PhoneNumber == null) { dto_us_bus.PhoneNumber = dto_bus_details.PhoneNumber; }
var user_business = new user_business()
{
bus_id = id,
bus_name = dto_us_bus.BusinessName,
bus_address = dto_us_bus.Address,
bus_phone = dto_us_bus.PhoneNumber,
};
db.Entry(user_business).State = EntityState.Modified;
try
{
await db.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!user_businessExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return StatusCode(HttpStatusCode.NoContent);
我发送的JSON工作正常,但是如果我发送BusinessName和Address(即如果我遗漏了PhoneNumber),它会将PhoneNumber更改为null,而不是将PhoneNumber保留在数据库中。
我认为这是因为我将值设置为DTO值(因此,如果它们缺失它将为空)但即使我不使用DTO,行为也是相同。我错过了什么,或者这只是PUT的工作方式?
由于
修改
我考虑过对数据库进行LINQ选择,然后检查每个变量&amp;如果它为null,则将其设置为从select中获取的数据,但是这不会起作用,就好像该值实际上是来自用户的null,它将使DB值保持原样。如果有一种方法我可以确定JSON调用中是否缺少它而不是它是否为空,这将起作用,但它看起来效率很低。
答案 0 :(得分:1)
这与PUT无关。如果您不发布电话号码,请求中将不会有一个,因此无论动词如何,绑定参数中都不会有一个。 MVC框架不知道数据库中的内容或您希望它做什么。
由您首先加载现有记录,然后仅分配您要更改的值。
一个好的开始是为您的动作方法参数使用适当的视图模型,该参数仅包含该动作方法所需的属性(这也有助于防止模型注入 - 人们包括您不需要它们的值包括)。
如果您无法知道在编译时将设置哪些字段,则您必须将空值视为未更改或更改为null。它并不能真正意味着两者。如果您希望用户能够将值设置为null,则必须执行以下操作:
如果您正在控制请求,第一个选项将是最简单的。如果原始值未更改,请确保在请求中发送原始值。