我創建了一個非常簡單的OData v4控制器。該控制器主要包含以下Pet
實體實體框架支持的CRUD方法:如何防止在ASP.NET Web API OData服務中發佈底稿?
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 }
但是,我可以簡單地忽略JSON請求負載中的Age
屬性,因此JSON解串器將使用默認值0
,而我希望返回400 Bad Request
狀態。這個問題被稱爲under-posting。
使用常規的WebApi控制器可以輕鬆解決該問題(解決方案描述爲here)。你只需要創建一個PetViewModel
,讓你的控制器接受PetViewModel
而不是實際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
方法接受PetViewModel
,而不是Pet
,我收到以下錯誤:
System.Net.Http.UnsupportedMediaTypeException: No MediaTypeFormatter is available to read an object of type 'PetViewModel' from content with media type 'application/json'.
at System.Net.Http.HttpContentExtensions.ReadAsAsync[T](HttpContent content, Type type, IEnumerable'1 formatters, IFormatterLogger formatterLogger, CancellationToken cancellationToken)
at System.Net.Http.HttpContentExtensions.ReadAsAsync(HttpContent content, Type type, IEnumerable'1 formatters, IFormatterLogger formatterLogger, CancellationToken cancellationToken)
at System.Web.Http.ModelBinding.FormatterParameterBinding.ReadContentAsync(HttpRequestMessage request, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger, CancellationToken cancellationToken)
那麼,有沒有什麼辦法來防止下在使用OData控制器時發貼?
在這種情況下,您可以使用RangeAttribute並在1到999之間指定它。然後'ModelState.IsValid'應該捕獲0值不在範圍內並返回BadRequest'狀態。另一種選擇是創建一個自定義過濾器並在映射到模型之前手動解析傳入的JSON,但這看起來像是矯枉過正。 – Igor
@Igor我已經使用第二種方法解決了問題,因爲需要區分默認值和空值的通用解決方案。如果您有興趣,請查看答案。感謝您的幫助! –