我创建了一个非常简单的 OData v4 控制器。控制器基本上包含以下实体的实体框架支持的 CRUD 方法Pet
:
public class Pet
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
public int Age { get; set; }
}
这里重要的Pet.Age
是不可为空的必需属性。
这是控制器本身(仅Post
显示方法):
public class PetController : ODataController
{
private DatabaseContext db = new DatabaseContext();
// POST: odata/Pet
public IHttpActionResult Post(Pet pet)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.Pet.Add(pet);
db.SaveChanges();
return Created(pet);
}
// Other controller methods go here...
}
这是我的WebApiConfig
控制器配置:
ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<Pet>("Pet");
config.MapODataServiceRoute("odata", "odata", builder.GetEdmModel());
现在,如果我想Pet
在我的数据库中创建一个新的,我会发出这样的POST
请求:
POST http://localhost:8080/odata/Pet
Content-type: application/json
{ Name: "Cat", Age: 5 }
但是,我可以简单地省略Age
JSON 请求负载中的属性,因此 JSON 反序列化器将使用默认值0
,而我希望400 Bad Request
返回一个状态。这个问题被称为发布不足。
使用常规 WebApi 控制器时可以轻松解决(解决方案在此处描述)。您只需创建 aPetViewModel
并使您的控制器接受 aPetViewModel
而不是实际Pet
实体:
public class PetViewModel
{
// Make the property nullable and set the Required attribute
// to distinguish between "zero" and "not set"
[Required]
public int? Age { get; set; }
// Other properties go here...
}
然后在您的控制器中,您只需转换PetViewModel
为Pet
实体并像往常一样将其保存到数据库中。
不幸的是,这种方法不适用于 OData 控制器:如果我将Post
方法更改为 acceptPetViewModel
而不是Pet
,我会收到以下错误:
System.Net.Http.UnsupportedMediaTypeException:没有 MediaTypeFormatter 可用于从媒体类型为“application/json”的内容中读取“PetViewModel”类型的对象。
在 System.Net.Http.HttpContentExtensions.ReadAsAsync[T](HttpContent 内容,类型类型,IEnumerable'1 格式化程序,IFormatterLogger 格式化程序记录器,CancellationToken 取消令牌)
在 System.Net.Http.HttpContentExtensions.ReadAsAsync(HttpContent 内容,Type 类型,IEnumerable'1 格式化程序,IFormatterLogger formatterLogger,CancellationToken cancelToken)
在 System.Web.Http.ModelBinding.FormatterParameterBinding.ReadContentAsync(HttpRequestMessage 请求,类型类型,IEnumerable`1 格式化程序,IFormatterLogger 格式化程序记录器,CancellationToken 取消令牌)
那么,在使用 OData 控制器时,有什么方法可以防止发布不足?