I think this is similar to the problems that were previously experienced in our projects.
You need to change the zip code for jQuery to the following:
$.ajax({ type: 'POST', url: '/api/api/Test', data: JSON.stringify({ ID: 29, MyWidget: null }), contentType: "application/json", dataType: 'json', timeout: 30000 }) .done(function (data) { }) .fail(function() { });
By default, jQuery 'posts' sends parameters as data encoded as url.
application / x-www-form-urlencoded
ID 29
Mywidget
ID = 29 & MyWidget =
Thus, he was deserialized absolutely correctly. MyWidget is an empty string, so it will have an empty value for the Widget class.
In addition, I recommend that you add the Formatters configuration for WebApi controllers:
public static void Register(HttpConfiguration config) {
Thus, for API calls you will only use JSON formatting.
UPDATE
The main difference is that the data encoded in the url form passed to the MVC will be processed at runtime and finally processed by DefaultModelBinder (if a custom binder is not available). Thus, data encoded as form-url is usually used for MVC, because usually the data is generated by HTML form mail. But the Web API does not rely on any particular design encoding. Therefore, it uses a specific mechanism (formatters) to analyze the data ... for example, json, as above. Thus, FormUrlEncodedMediaTypeFormatter from System.Net.Http.Formatting and DefaultModelBinder from System.Web.Mvc handles the empty string differently.
For DefaultModelBinder, an empty string will be converted to zero. By analyzing the code, I can decide that the BindModel method first creates an empty model:
if (model == null) { model = CreateModel(controllerContext, bindingContext, modelType); }
After filling in the properties:
Finally, GetBinder will return a fallbackBinder for the widget type (property type). And fallbackBinder itself will call ConvertSimpleType, where the string is processed as follows:
string valueAsString = value as string; if (valueAsString != null && String.IsNullOrWhiteSpace(valueAsString)) { return null; }
I think there are no standards describing the conversion of URL encoded strings to C # objects. Therefore, I do not know which one is correct. In any case, I'm sure you need to pass json through AJAX calls, not url encoded data.