【问题标题】:ViewModel passed into WebApi method is null传入 WebApi 方法的 ViewModel 为 null
【发布时间】:2013-07-25 21:46:37
【问题描述】:

不知道为什么我会遇到这个问题。我以前做过,但查看以前的项目没有任何帮助。我确定我缺少配置或其他东西。

我在一个 WebForms 4.5 项目中有一个 ApiController,用于从数据存储区 (SQL Server CE 4.0) 检索和更新数据。

我已经定义了以下 POST 方法来处理向产品添加属性记录...

    [HttpPost]
    public void AddPropertyToProduct([FromBody]ProductPropertyViewModel prodProp)
    {
        Mapper.CreateMap<ProductPropertyViewModel, ProductProperty>();
        ProductProperty property = Mapper.Map<ProductProperty>(prodProp);

        ProductRepository.Instance.AddProperty(property.ProductId, property);
        ProductRepository.Instance.SaveChanges();
    }

ProductPropertyViewModel 参数是我使用的 ViewModel,而不是数据模型...

public class ProductPropertyViewModel
{
    public Int64 Id { get; set; }

    public Int64 ProductId { get; set; }

    public String PropertyName { get; set; }

    public String PropertyValue { get; set; }

    public String Comments { get; set; }

    public DateTime DateAdded { get; set; }

    public DateTime DateUpdated { get; set; }

}

调用服务的客户端脚本发送一个 JSON 字符串,该字符串与属性的 ViewModel 属性相匹配...

var addPropertyToProduct = function (propertyViewModel, productId, isAsync, fnSuccess, fnError) {

    var methodUrl = "/api/ProductPropertyAPI/AddPropertyToProduct/"
    var ret = null;
    //
    // Make sure that the ProductId is specified as part of the ViewModel
    propertyViewModel.ProductId = productId;
    //
    // make sure that the propertyViewModel is reduced to JSON for being passed to the server.
    // Example : {"Id": 0, "ProductId":5,"PropertyName":"Engine Size","PropertyValue":"300cc","Comments":"Some comment","DateAdded":"07/25/2013","DateUpdated":"07/25/2013"}
    var jsonData = ko.toJSON(propertyViewModel);
    $.ajax({
        type: "POST",
        data: jsonData,
        async: isAsync,
        contentType: 'application/json;charset=utf-8',
        url: methodUrl,
        success: function (data) {
            //#region console log
            var logMsg = "AJAX.ProductPropertyAPI.AddPropertyToProduct ( "+ JSON.stringify(jsonData) +" ): RESPONSE : " + JSON.stringify(data);
            console.log(logMsg);
            //#endregion
            if (typeof fnSuccess === 'function') {
                fnSuccess(data);
            }
            else {
                defaultSuccess(data);
            }
        },
        error: function (data) {

            if (typeof fnError === 'function') {
                fnError(data);
            }
            else {
                defaultError(data);
            }
        }
    });
}

我遇到的问题是,当请求发布到服务的 AddPropertyToProduct 方法时,prodProp 参数是 NULL 而不是 ViewModel 的实例。据我了解,WebAPI 知道将 JSON 数据映射到 ProductPropertyViewModel 对象。

我确信我在这里忽略了一些东西,但无法弄清楚它是什么。谁能看到我错过了什么?

谢谢, G

更新:添加 Fiddler 数据

这是我通过 Fiddler 发送的请求。

POST http://localhost:55556/api/ProductPropertyAPI/AddPropertyToProduct HTTP/1.1
User-Agent: Fiddler
Host: localhost:55556
ContentType: 'application/json;charset=utf-8'
Content-Length: 155

{"Id": 0, "ProductId":5,"PropertyName":"Engine Size","PropertyValue":"300cc","Comments":"Some comment","DateAdded":"07/25/2013","DateUpdated":"07/25/2013"}

更新:添加了来自 IE 开发者工具的 $.Ajax 请求标头

Key Value
Request POST http://localhost:55556/api/ProductPropertyAPI/AddPropertyToProduct/ HTTP/1.1
Accept  */*
Content-Type    application/json;charset=utf-8
X-Requested-With    XMLHttpRequest
Referer http://localhost:55556/Admin/ProductManager.aspx
Accept-Language en-US
Accept-Encoding gzip, deflate
User-Agent  Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)
Host    localhost:55556
Content-Length  129
DNT 1
Proxy-Connection    Keep-Alive
Pragma  no-cache
Cookie  __atuvc=38%7C8; __AntiXsrfToken=63a0ede574be4aa9a19e153474320450; ASPSESSIONIDACBTCRRS=FDDPEJIBPDFEODAHOEMBOOFK; ASPSESSIONIDCABTDTRT=AANBPPFCEFOBMAEFMMPMMFLF; ASPSESSIONIDAAARDSRS=LODHOFGCLJILEEEHICHGLNLA; ASPSESSIONIDCCDTCSQT=NHOJPJGCOECNJBIDGGKIALFG; ASP.NET_SessionId=xh4xctv0mvq2zb454hkb1f3z

【问题讨论】:

  • 你试过删除[FromBody]属性吗?
  • 是的......我尝试的第一件事。
  • 你能用fiddler之类的东西来检查帖子吗?仔细检查内容类型并确保 Json 可以映射到您的视图模型中。您也可以尝试将dataType: "json" 添加到您的ajax 方法中。
  • 是的......我一直在这样做。我已向 OP 添加了 Fiddler 请求的示例。
  • 查看您的 Fiddler 跟踪,标头应该是 Content-Type 而不是 ContentType...所以 Web Api 认为请求中没有 content-type 标头并且没有反序列化,因为它不知道要使用哪个格式化程序来反序列化,因此它在这里为类型创建一个默认值..在您的情况下将为空...奇怪的是 $.ajax 没有设置正确的标题..

标签: jquery asp.net ajax webforms asp.net-web-api


【解决方案1】:

我只是将您的代码复制粘贴到新项目中,但它失败了。

"Message":"An error has occurred.",
"ExceptionMessage":"Object reference not set to an instance of an object.",
"ExceptionType":"System.NullReferenceException"

我假设您遇到了同样的错误。但是在我删除之后:

contentType: 'application/json;charset=utf-8',

成功了。

我的完整 ajax 请求:

// I used static jsonData because you're getting the correct values in 
// your fiddler so this is definitely not causing any issues
var jsonData = { "Id": 0, "ProductId": 5, "PropertyName": "Engine Size", "PropertyValue": "300cc", "Comments": "Some comment", "DateAdded": "07/25/2013", "DateUpdated": "07/25/2013" };
var methodUrl = "/api/test/AddPropertyToProduct/";
$.ajax({
    type: "POST",
    data: jsonData,
    //async: isAsync,
    //contentType: 'application/json;charset=utf-8',
    url: methodUrl,
    success: function (data) {
        console.log('Success: ', data);
    },
    error: function (data) {
        console.log('Error: ', data);
    }
});

我使用的动作方法:

[HttpPost]
public string AddPropertyToProduct(ProductPropertyViewModel prodProp)
{
    return prodProp.PropertyName;
}

【讨论】:

  • 您对错误消息以及从 Ajax 请求中删除 contentType 是正确的(虽然我不明白为什么这是一个问题,实际上我认为这是必要的)。 prodProp 参数不再为 NULL,但它也没有加载我试图传入的数据。它加载了每个字段的默认值(字符串为 null,int64 为 0和 DateTime 是 1/1/0001 12:00:00AM),而不是将 JSON 加载到对象实例中。
  • 很确定 contentType 在 asp webform webmethods 中使用,但您在 web api 中不需要它。至于默认值:您的提琴手是否仍在发送正确的数据?在我的测试中,我的函数返回的内容与我发送的内容相同,在上面的示例中为“引擎大小”。
  • 我将此标记为答案,因为它解决了 NULL 问题,但我仍然不明白为什么正在传递给服务函数的实例充满了默认值。我会继续研究它。我的直觉告诉我,仍然缺少一些偏远地区的配置设置。
猜你喜欢
  • 2014-05-08
  • 2020-01-12
  • 1970-01-01
  • 1970-01-01
  • 2021-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-04
相关资源
最近更新 更多