ฉันคิดว่ามันคล้ายกับปัญหาที่เคยพบในโครงการของเรา
คุณต้องเปลี่ยนรหัสไปรษณีย์สำหรับ 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
application/x-www-form-urlencoded
ID 29
MyWidget
ID=29&MyWidget=
ดังนั้นมันจึงถูกดีซีเรียลไลซ์อย่างถูกต้องอย่างแน่นอน MyWidget เป็นสตริงว่าง ดังนั้นจะมีค่าว่างของคลาส Widget
นอกจากนี้ ฉันขอแนะนำให้คุณเพิ่มการกำหนดค่า Formatters สำหรับคอนโทรลเลอร์ 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 ไม่ได้ขึ้นอยู่กับการเข้ารหัสเฉพาะใดๆ จากการออกแบบ ดังนั้นจึงใช้กลไกเฉพาะ (ตัวจัดรูปแบบ) เพื่อแยกวิเคราะห์ข้อมูล... เช่น json เหมือนที่กล่าวข้างต้น ดังนั้น FormUrlEncodedMediaTypeFormatter จาก System.Net.Http.Formatting และ DefaultModelBinder จาก System.Web.Mvc จัดการสตริงว่างแตกต่างกัน
สำหรับ DefaultModelBinder สตริงว่างจะถูกแปลงเป็นโมฆะ กำลังวิเคราะห์โค้ด ฉันสามารถตัดสินใจได้ว่าวิธี 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
person
Maxim
schedule
06.01.2016
Model
ของคุณจะสร้างWidget
ในตัวสร้างเริ่มต้นและกำหนดให้กับMyWidget
ใช่ไหม - person dbc   schedule 06.01.2016