title: How to prevent under-posting in ASP.NET Web API OData service?
body: <p>I have created a very simple OData v4 controller. The controller basically contains Entity Framework-backed CRUD methods for the following <code>Pet</code> entity:</p>
  
  <pre><code>public class Pet
  {
      public int Id { get; set; }
  
      [Required]
      public string Name { get; set; }
  
      public int Age { get; set; }
  }
  </code></pre>
  
  <p>An important thing here is that <code>Pet.Age</code> is the non-nullable required property.</p>
  
  <p>Here is the controller itself (only <code>Post</code> method is shown):</p>
  
  <pre><code>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...
  }
  </code></pre>
  
  <p>And this is my <code>WebApiConfig</code> controller configuration:</p>
  
  <pre><code>ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
  builder.EntitySet&lt;Pet&gt;("Pet");
  config.MapODataServiceRoute("odata", "odata", builder.GetEdmModel());
  </code></pre>
  
  <p>Now if I want to create a new <code>Pet</code> in my database, I issue a <code>POST</code> request like this:</p>
  
  <pre><code>POST http://localhost:8080/odata/Pet
  Content-type: application/json
  
  { Name: "Cat", Age: 5 }
  </code></pre>
  
  <p>However, I can simply omit the <code>Age</code> property in JSON request payload, so JSON deserializer will use a default value of <code>0</code>, while I want a <code>400 Bad Request</code> status to be returned instead. This problem is called under-posting.</p>
  
  <p>It can be easily solved when using regular WebApi controllers (the solution is described <a href="http://www.asp.net/web-api/overview/formats-and-model-binding/model-validation-in-aspnet-web-api" rel="nofollow">here</a>). You just create a <code>PetViewModel</code> and make your controller to accept a <code>PetViewModel</code> instead of an actual <code>Pet</code> entity:</p>
  
  <pre><code>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...
  }
  </code></pre>
  
  <p>Then in your controller you just convert <code>PetViewModel</code> to <code>Pet</code> entity and save it to the database as usual.</p>
  
  <p>Unfortunately, this approach does not work with OData controllers: if I change my <code>Post</code> method to accept <code>PetViewModel</code> instead of <code>Pet</code>, I receive the following error:</p>
  
  <blockquote>
    <p>System.Net.Http.UnsupportedMediaTypeException: No MediaTypeFormatter is available to read an object of type 'PetViewModel' from content with media type 'application/json'.</p>
    
    <p>at System.Net.Http.HttpContentExtensions.ReadAsAsync[T](HttpContent content, Type type, IEnumerable'1 formatters, IFormatterLogger formatterLogger, CancellationToken cancellationToken)</p>
    
    <p>at System.Net.Http.HttpContentExtensions.ReadAsAsync(HttpContent content, Type type, IEnumerable'1 formatters, IFormatterLogger formatterLogger, CancellationToken cancellationToken)</p>
    
    <p>at System.Web.Http.ModelBinding.FormatterParameterBinding.ReadContentAsync(HttpRequestMessage request, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger, CancellationToken cancellationToken)</p>
  </blockquote>
  
  <p>So, is there any way to prevent under-posting when using OData controllers?</p>