Web API复杂参数属性全部为空

2020/12/18 16:11 · jquery ·  · 0评论

我有一个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。因此,例如,如果我传入此对象:

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个控制器类,而Posts可以在所有这些类中工作...

对于Asp.Net WebAPI,这似乎是一个常见问题。

通常,空对象的原因是将json对象反序列化为C#对象。
不幸的是,调试非常困难-因此很难找到问题所在。


我更喜欢只将完整的json作为对象发送,然后手动反序列化。
至少通过这种方式,您会得到真正的错误而不是空值。


如果将方法签名更改为接受对象,请使用JsonConvert:

public HttpResponseMessage Post(Object model)
        {
            var jsonString = model.ToString();
            PreferenceRequest result = JsonConvert.DeserializeObject<PreferenceRequest>(jsonString);
        }

也许会有帮助,我遇到了同样的问题。

一切运行良好,突然,每个属性都被默认。

经过一些快速测试,我发现是导致问题的原因是[可序列化]

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;
}

因此,我知道有3个可能的问题,该值在哪里不绑定:

  1. 没有公共的参数ctor
  2. 属性不是公共可设置的
  3. 存在绑定错误,导致ModelState.Valid == false-典型问题是:值类型不兼容(json对象为字符串,non-guid等)

因此,我正在考虑是否应在API调用中应用过滤器,如果绑定导致错误,该过滤器将返回错误!

我猜问题是您的控制器期望[FromBody]的内容类型,请尝试将您的控制器更改为

public HttpResponseMessage Post(PreferenceRequest request)

和阿贾克斯

$.ajax({
    type: "POST",
    data: JSON.stringify(request);,
    dataType: 'json',
    contentType: "application/json",
    url: "http://localhost:1111/service/User",

顺便说一下,用javascript创建模型可能不是最佳实践。

使用@blorkfish发布的这项技术效果很好:

public HttpResponseMessage Post(Object model)
    {
        var jsonString = model.ToString();
        PreferenceRequest result = JsonConvert.DeserializeObject<PreferenceRequest>(jsonString);
    }

我有一个参数对象,它有几个本机类型和两个作为属性的对象。这些对象具有标记为internal的构造函数,并且对jsonString的JsonConvert.DeserializedObject调用给出了错误:

找不到用于类型ChildObjectB的构造函数。一个类应该具有一个默认构造函数,一个带有参数的构造函数或一个标有JsonConstructor属性的构造函数。

我将构造函数更改为public,当我用真实对象替换Object模型参数时,它现在正在填充参数对象。谢谢!

我知道,这有点晚了,但是我遇到了同样的问题。@blorkfish的答案也对我有用,但使我找到了不同的解决方案。我的复杂对象的其中一部分缺少缺少参数的构造函数。添加此构造函数后,Put和Post请求都开始按预期方式工作。

我遇到了同样的问题。需要解决的问题是确保JSON到参数类的所有可序列化属性都已获取;组; 明确定义的方法。不要依赖C#自动属性语法!希望在更高版本的asp.net中解决此问题。

聚会晚了一点,但是我遇到了同样的问题,解决方法是在您的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");
    }

我也遇到了这个问题,经过从调试到调试的大量时间,研究发现该问题不是由Content-Type或Type $ Ajax属性引起的,而是由我的JSON对象上的NULL值引起的,这是一个非常不礼貌的问题,因为POST既不起作用,但一旦修复了NULL值,则POST很好,并且将其本地转换为以下代码:

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; }
    }

希望对您有所帮助。

昨天这个问题困扰着我整整一个工作日,因此我想补充一些可能在相同情况下帮助他人的内容。

我使用Xamarin Studio创建了我的angular和web api项目。在调试过程中,该对象有时会变为null,而其他时候会成为一个填充对象。只有当我开始在Visual Studio中调试项目时,每个发布请求中都会填充我的对象。在Xamarin Studio中进行调试时,这似乎是一个问题。

如果您在另一个IDE中遇到此空参数问题,请尝试在Visual Studio中尝试调试。

今天,我遇到了与您相同的问题。当我POSTajax控制器发送请求时,会收到带有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请求有效负载

这是没有的请求有效载荷 JSON.stringify

请求有效负载而无需JSON.stringify

而且,不要忘了,当事情变得神奇起来时,您就会使用它Google Chrome来测试Web应用程序。不时清空缓存并进行硬重装

我遇到了同样的问题,对我来说,解决方案是确保我的类属性的类型与json属性匹配,我的意思是

Json: "attribute": "true"

应该被视为字符串而不是布尔值,看起来像如果您遇到这样的问题,那么错误属性下的所有属性将默认为null

今天我也遇到了同样的问题。尝试所有这些方法之后,从Azure调试API并调试Xamarin Android应用程序,事实证明这是参考更新问题。请记住要确保您的API已更新Newtonsoft.JSON NUGET包(如果正在使用)。

其他问题均未解决我的问题,因此值得考虑以下解决方案:

我有以下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'以便反序列化程序知道我没有尝试访问该属性。

我面对这个问题,这解决了我

  1. 在模型中使用nuget包newton使用属性[JsonProperty(“ json请求中的属性名称”)]
  2. 如果您序列化对象仅调用PostAsync

像那样

var json = JsonConvert.SerializeObject(yourobject);
var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json");
var response = await client.PostAsync ("apiURL", stringContent);
  1. 如果不起作用,请从您的api中删除[from body]

就我而言,当我添加时,问题就解决了

获取{}设置{}

对参数类的定义:

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;
    }

HttpGet

public object Get([FromBody]object requestModel)
{
    var jsonstring = JsonConvert.SerializeObject(requestModel);
    RequestModel model = JsonConvert.DeserializeObject<RequestModel>(jsonstring);
}
  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 /打字稿

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],它确实起作用了。因此,请检查数据类型。

本文地址:http://jquery.askforanswer.com/web-apifuzacanshushuxingquanbuweikong.html
文章标签: ,   ,   ,   ,  
版权声明:本文为原创文章,版权归 admin 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!