Я думаю, что это похоже на проблемы, ранее испытанные в наших проектах.
Вы должны изменить почтовый индекс для Jquery к следующему:
$.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() {
});
К «сообщений» по умолчанию Jquery посылает параметры, как данные формы для URL-кодирования.
применение/х-WWW-форм-urlencoded
ID 29
MyWidget
ID = 29 = & MyWidget
Так было десериализации совсем правильно. MyWidget - пустая строка, поэтому у нее будет пустое значение класса Widget.
Кроме того, я рекомендую вам добавить конфигурацию Форматтеров для контроллеров WebAPI:
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
// Formatters
JsonMediaTypeFormatter json = config.Formatters.JsonFormatter;
config.Formatters.Clear();
config.Formatters.Add(json);
}
Таким образом, вы будете использовать только JSON-форматировщик для вызовов API.
ОБНОВЛЕНИЕ
Главное отличие, что форма-URL-кодированные данные, передаваемые в контроллер MVC будет обработан время выполнения и, наконец, обрабатываются DefaultModelBinder (если заказ связующее не доступен). Таким образом, данные, закодированные как form-url, обычно используются для MVC, потому что обычно данные генерируются почтой HTML-формы. Но Web API не полагается на какую-либо конкретную кодировку по дизайну. Поэтому он использует конкретный механизм (formatters) для анализа данных ... например, json, как и выше. Таким образом FormUrlEncodedMediaTypeFormatter из System.Net.Http.Formatting и DefaultModelBinder из System.Web.Mvc обрабатывает пустую строку по-разному.
Для пустой строки DefaultModelBinder будет преобразовано значение null. Анализ кода я могу решить, что метод BindModel во-первых, создает пустую модель:
if (model == null)
{
model = CreateModel(controllerContext, bindingContext, modelType);
}
После заполнит свойства:
// call into the property's model binder
IModelBinder propertyBinder = Binders.GetBinder(propertyDescriptor.PropertyType);
object originalPropertyValue = propertyDescriptor.GetValue(bindingContext.Model);
ModelMetadata propertyMetadata = bindingContext.PropertyMetadata[propertyDescriptor.Name];
propertyMetadata.Model = originalPropertyValue;
ModelBindingContext innerBindingContext = new ModelBindingContext()
{
ModelMetadata = propertyMetadata,
ModelName = fullPropertyKey,
ModelState = bindingContext.ModelState,
ValueProvider = bindingContext.ValueProvider
};
object newPropertyValue = GetPropertyValue(controllerContext, innerBindingContext, propertyDescriptor, propertyBinder);
И наконец GetBinder вернется fallbackBinder для типа Widget (тип недвижимости). И сама fallbackBinder будет называть ConvertSimpleType, где строка обрабатываются следующим образом:
string valueAsString = value as string;
if (valueAsString != null && String.IsNullOrWhiteSpace(valueAsString))
{
return null;
}
Я предполагаю, что нет каких-либо стандартов, описывающих преобразование URL-закодированных строк на объекты C#. Поэтому я не знаю, какой из них правильный. В любом случае я уверен, что вам нужно передать json через вызовы AJAX, а не данные, закодированные в форме-url.
Нет никаких шансов, что ваша 'Model' построит' Widget' в своем конструкторе по умолчанию и назначит его 'MyWidget', не так ли? – dbc
Какую версию веб-API вы используете? –
@dbc, класс не такой, как вы его видите. Конструктор не указан. И кроме того, если бы это была проблема с конструктором, это произошло бы для обоих контроллеров. –