我有一个Web API服务调用,用于更新用户的首选项。不幸的是,当我从jQuery ajax调用中调用此POST方法时,请求参数对象的属性始终为null(或默认值),而不是传入的内容。如果我使用REST客户端调用相同的方法(我使用Postman),它工作得很漂亮。我无法弄清楚我做错了什么,但我希望有人之前见过这个。这很简单......
这是我的请求对象:
public class PreferenceRequest
{
[Required]
public int UserId;
public bool usePopups;
public bool useTheme;
public int recentCount;
public string[] detailsSections;
}
这是UserController类中的控制器方法:
public HttpResponseMessage Post([FromBody]PreferenceRequest request)
{
if (request.systemsUserId > 0)
{
TheRepository.UpdateUserPreferences(request.UserId, request.usePopups, request.useTheme,
request.recentCount, request.detailsSections);
return Request.CreateResponse(HttpStatusCode.OK, "Preferences Updated");
}
else
{
return Request.CreateErrorResponse(HttpStatusCode.NotAcceptable, "You must provide User ID");
}
}
这是我的ajax电话:
var request = {
UserId: userId,
usePopups: usePopups,
useTheme: useTheme,
recentCount: recentCount,
detailsSections: details
};
$.ajax({
type: "POST",
data: request,
url: "http://localhost:1111/service/User",
success: function (data) {
return callback(data);
},
error: function (error, statusText) {
return callback(error);
}
});
我尝试过设置dataType& contentType到几个不同的东西(' json',' application / json'等)但是请求对象的属性总是默认为null或null。所以,例如,如果我传入这个对象:
var request = {
UserId: 58576,
usePopups: false,
useTheme: true,
recentCount: 10,
detailsSections: ['addresses', 'aliases', 'arrests', 'events', 'classifications', 'custody', 'identifiers', 'phone', 'remarks', 'watches']
}
我可以看到一个完全填充的请求对象,其中包含上面列出的有效值。但是在Web API控制器中,请求就在那里,但属性如下:
UserId: 0,
usePopups: false,
useTheme: false,
recentCount: 0,
detailsSections: null
仅供参考 - 我没有在这个项目中使用任何ASP.Net MVC或ASP.NET页面,只使用Web API作为服务并使用jQuery $ .ajax进行所有调用。
知道我在这里做错了什么吗?谢谢!
更新:我只想说明我在其他控制器的同一个Web API项目中有很多方法可以执行此操作完全相同的事情,我正在调用完全相同,它们完美无缺!我花了一个上午比较各种调用,并且方法或标题似乎没有任何区别,但它只是不适用于这种特定的方法。
我也尝试过切换到Put方法,但我得到完全相同的结果 - 请求对象进来,但没有填充正确的值。令人沮丧的是,我在这个项目中有大约20个控制器类,并且帖子在所有这些中工作......
答案 0 :(得分:52)
这似乎是Asp.Net WebAPI的常见问题 通常,null对象的原因是将json对象反序列化为C#对象。不幸的是,它很难调试 - 因此找到你的问题所在 我更喜欢将完整的json作为对象发送,然后手动反序列化。至少这样你会得到真正的错误而不是空值 如果更改方法签名以接受对象,则使用JsonConvert:
public HttpResponseMessage Post(Object model)
{
var jsonString = model.ToString();
PreferenceRequest result = JsonConvert.DeserializeObject<PreferenceRequest>(jsonString);
}
答案 1 :(得分:10)
也许它会有所帮助,我遇到了同样的问题。
一切都运作良好,突然之间,每个房产都被拖欠了。
经过一些快速测试后,我发现导致问题的是[Serializable] :
public IHttpActionResult Post(MyComplexClass myTaskObject)
{
//MyTaskObject is not null, but every member are (the constructor get called).
}
这是我班级的片段:
[Serializable] <-- have to remove that [if it was added for any reason..]
public class MyComplexClass()
{
public MyComplexClass ()
{
..initiate my variables..
}
public string blabla {get;set;}
public int intTest {get;set;
}
答案 2 :(得分:4)
我想问题是你的控制器期待[FromBody]的内容类型,尝试将你的控制器更改为
public HttpResponseMessage Post(PreferenceRequest request)
和ajax到
$.ajax({
type: "POST",
data: JSON.stringify(request);,
dataType: 'json',
contentType: "application/json",
url: "http://localhost:1111/service/User",
顺便说一句,在javascript中创建模型可能不是最佳实践。
答案 3 :(得分:4)
使用@blorkfish发布的这项技术非常有效:
public HttpResponseMessage Post(Object model)
{
var jsonString = model.ToString();
PreferenceRequest result = JsonConvert.DeserializeObject<PreferenceRequest>(jsonString);
}
我有一个参数对象,它有几个原生类型和几个对象作为属性。对象具有标记为internal的构造函数,并且jsonString上的JsonConvert.DeserializedObject调用给出了错误:
无法找到用于ChildObjectB类型的构造函数。一类 应该有一个默认的构造函数,一个构造函数 参数或用JsonConstructor属性标记的构造函数。
我将构造函数更改为public,当我将Object模型参数替换为真实对象时,它现在填充参数对象。谢谢!
答案 4 :(得分:3)
因此,我知道有3个可能的问题,该值不绑定在何处:
所以我正在考虑是否应在API调用中应用一个过滤器,如果绑定导致错误,该过滤器将返回错误!
答案 5 :(得分:2)
我知道,这有点晚了,但我遇到了同样的问题。 @ blorkfish的回答也适用于我,但引导我找到了一个不同的解决方案。我的复杂对象的一部分缺少无参数构造函数。添加此构造函数后,Put和Post请求都按预期开始工作。
答案 6 :(得分:2)
派对有点晚了,但是我遇到了同样的问题,修复程序在你的ajax调用中声明了contentType:
var settings = {
HelpText: $('#help-text').val(),
BranchId: $("#branch-select").val(),
Department: $('input[name=departmentRadios]:checked').val()
};
$.ajax({
url: 'http://localhost:25131/api/test/updatesettings',
type: 'POST',
data: JSON.stringify(settings),
contentType: "application/json;charset=utf-8",
success: function (data) {
alert('Success');
},
error: function (x, y, z) {
alert(x + '\n' + y + '\n' + z);
}
});
您的API控制器可以像这样设置:
[System.Web.Http.HttpPost]
public IHttpActionResult UpdateSettings([FromBody()] UserSettings settings)
{
//do stuff with your UserSettings object now
return Ok("Successfully updated settings");
}
答案 7 :(得分:2)
我也遇到了这个问题,经过debbug的大量研究,研究发现该问题不是由Content-Type或Type $ Ajax属性引起的,而是由JSON对象上的NULL值引起的,这是非常不礼貌的问题,因为POST既无法执行,但一旦修复了NULL值,则POST很好,并且将其本地转换为我的respuestaComparacion类,代码如下:
JSON
respuestaComparacion: {
anioRegistro: NULL, --> cannot cast to BOOL
claveElector: NULL, --> cannot cast to BOOL
apellidoPaterno: true,
numeroEmisionCredencial: false,
nombre: true,
curp: NULL, --> cannot cast to BOOL
apellidoMaterno: true,
ocr: true
}
控制器
[Route("Similitud")]
[HttpPost]
[AllowAnonymous]
public IHttpActionResult SimilitudResult([FromBody] RespuestaComparacion req)
{
var nombre = req.nombre;
}
班级
public class RespuestaComparacion
{
public bool anioRegistro { get; set; }
public bool claveElector { get; set; }
public bool apellidoPaterno { get; set; }
public bool numeroEmisionCredencial { get; set; }
public bool nombre { get; set; }
public bool curp { get; set; }
public bool apellidoMaterno { get; set; }
public bool ocr { get; set; }
}
希望获得帮助。
答案 8 :(得分:1)
我遇到了同样的问题。所需的修复是确保您的JSON到参数类的所有可序列化属性都得到;组;明确定义的方法。不要依赖C#自动属性语法!希望在以后的asp.net版本中修复此问题。
答案 9 :(得分:0)
public class CompanyRequestFilterData
{
public string companyName { get; set; }
public string addressPostTown { get; set; }
public string businessType { get; set; }
public string addressPostCode{ get; set; }
public bool companyNameEndWith{ get; set; }
public bool companyNameStartWith{ get; set; }
public string companyNumber{ get; set; }
public string companyStatus{ get; set; }
public string companyType{ get; set; }
public string countryOfOrigin{ get; set; }
public DateTime? endDate{ get; set; }
public DateTime? startDate { get; set; }
}
webapi控制器
[HttpGet("[action]"),HttpPost("[action]")]
public async Task<IEnumerable<CompanyStatusVm>> GetCompanyRequestedData(CompanyRequestFilterData filter)
{}
jsvascript / typescript
export async function GetCompanyRequesteddata(config, payload, callback, errorcallback) {
await axios({
method: 'post',
url: hostV1 + 'companydata/GetCompanyRequestedData',
data: JSON.stringify(payload),
headers: {
'secret-key': 'mysecretkey',
'Content-Type': 'application/json'
}
})
.then(res => {
if (callback !== null) {
callback(res)
}
}).catch(err => {
if (errorcallback !== null) {
errorcallback(err);
}
})
}
这是工作中的一个c#核心3.1
我的案例是bool数据类型,而我已将字符串更改为bool [companyNameEndWith]和[companyNameStartWith],它确实起作用了。因此,请检查数据类型。
答案 10 :(得分:0)
HttpGet
public object Get([FromBody]object requestModel)
{
var jsonstring = JsonConvert.SerializeObject(requestModel);
RequestModel model = JsonConvert.DeserializeObject<RequestModel>(jsonstring);
}
答案 11 :(得分:0)
就我而言,添加时已解决问题
获取{}设置{}
到参数类定义:
public class PreferenceRequest
{
public int UserId;
public bool usePopups {get; set;}
public bool useTheme {get; set;}
public int recentCount {get; set;}
public string[] detailsSections {get;set;}
}
代替:
public class PreferenceRequest
{
[Required]
public int UserId;
public bool usePopups;
public bool useTheme;
public int recentCount;
public string[] detailsSections;
}
答案 12 :(得分:0)
我遇到了这个问题,将其解决了
喜欢
istream& operator>>(istream& is, Temps& t){
//assume format (max----min)
return is >> t.max >> t.min;
}
答案 13 :(得分:0)
我的问题没有其他任何答案可以解决,因此值得考虑以下解决方案:
我有以下DTO和控制器方法:
public class ProjectDetailedOverviewDto
{
public int PropertyPlanId { get; set; }
public int ProjectId { get; set; }
public string DetailedOverview { get; set; }
}
public JsonNetResult SaveDetailedOverview(ProjectDetailedOverviewDto detailedOverview) { ... }
因为我的DTO具有与参数同名的属性(detailedOverview),所以反序列化器感到困惑,并试图用字符串而不是整个复杂对象填充参数。
解决方案是将控制器方法参数的名称更改为'overview'
,以使反序列化器知道我没有尝试访问该属性。
答案 14 :(得分:0)
我今天也遇到了同样的问题。尝试所有这些方法之后,从Azure调试API并调试Xamarin Android应用程序,事实证明这是参考更新问题。请记住要确保您的API更新了Newtonsoft.JSON NUGET包(如果正在使用)。
答案 15 :(得分:0)
我遇到了同样的问题,我的解决方案是确保我的类属性的类型与json属性匹配,我的意思是
Json: "attribute": "true"
应该被视为字符串而不是布尔值,看起来如果你有这样的问题,故障属性下面的所有属性都将默认为null
答案 16 :(得分:0)
今天,我和你的问题一样。当我从POST
发送ajax
请求时,控制器会收到带有Null
的空对象和默认属性值。
方法是:
[HttpPost]
public async Task<IActionResult> SaveDrawing([FromBody]DrawingModel drawing)
{
try
{
await Task.Factory.StartNew(() =>
{
//Logic
});
return Ok();
}
catch(Exception e)
{
return BadRequest();
}
}
我的Content-Type
是正确的,其他一切也都是正确的。在尝试了很多东西后,我发现像这样发送对象:
$.ajax({
url: '/DrawingBoard/SaveDrawing',
type: 'POST',
contentType: 'application/json',
data: dataToPost
}).done((response) => { });
不会工作,但是这样发送却有效:
$.ajax({
url: '/DrawingBoard/SaveDrawing',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify(dataToPost)
}).done((response) => { });
是的,丢失的JSON.stringify()
导致整个问题,并且无需将=
或其他任何内容作为前缀或后缀添加到JSON.stringify
。
挖了一下之后。我发现请求有效负载的格式在两个请求之间完全不同
这是带有JSON.stringify
这是没有JSON.stringify
不要忘记,当事情变得神奇并且您使用Google Chrome
来测试您的网络应用程序时。 Do Empty cache and hard reload不时{。}}
答案 17 :(得分:0)
由于这个问题昨天几乎整整一个工作日让我很烦恼,我想在同样的情况下添加可能有助于其他人的事情。
我使用Xamarin Studio创建我的角度和web api项目。在调试期间,对象有时会通过null,有时会作为填充对象。只有当我开始在Visual Studio中调试我的项目时,我的对象才会在每个帖子请求中填充。在Xamarin Studio中进行调试时,这似乎是一个问题。
如果您遇到与另一个IDE的此null参数问题,请尝试在Visual Studio中进行调试。