【问题标题】:AngularJS ngResource POST object is Null in C# Web APIAngularJS ngResource POST 对象在 C# Web API 中为 Null
【发布时间】:2016-11-08 05:43:12
【问题描述】:

我的问题是,当我将完整的 Javascript 对象发送到我的 Web API 控制器时,我总是得到空值。即使我有一个完整的对象,我也需要指定每个属性和值,如下所示。如何让 Web API 接受现成的 Javascript 对象并正确绑定?

C# Web API 控制器:

[Route("addcredentials/{salesId}")]
[HttpPost]
public IHttpActionResult AddCredentials([FromUri] int salesId, [FromBody] ScriveCredentials credentials)
{
    return Ok(credentials);
}

C# 凭据对象:

public class Credentials
{
    public string ClientIdentifier { get; set; }

    public string ClientSecret { get; set; }

    public string TokenIdentifier { get; set; }

    public string TokenSecret { get; set; }
}

传递给资源的 Javascript 对象,进一步保存为“结果”:

{ClientIdentifier: "a", ClientSecret: "b", TokenIdentifier: "c", TokenSecret: "d"}

资源方法:

addCredentials: {
    method: 'POST',
    url: 'api/addcredentials/:userSalesId'
}

导致空值的用法:

userResource.addCredentials({ userSalesId: user.SalesId }, { credentials: result}).$promise.then(function (data) {
    console.log(data);
});

此请求的负载:

{"credentials":{"ClientIdentifier":"a","ClientSecret":"b","TokenIdentifier":"c","TokenSecret":"d"}}

可行但似乎过于复杂的用法:

userResource.addCredentials({ userSalesId: user.SalesId }, { ClientIdentifier: result.ClientIdentifier, ClientSecret: result.ClientSecret, TokenIdentifier: result.TokenIdentifier, TokenSecret: result.TokenSecret }).$promise.then(function (data) {
    console.log(data);
});

请求负载:

{"ClientIdentifier":"a","ClientSecret":"b","TokenIdentifier":"c","TokenSecret":"d"}

更新

尝试了以下,它也没有工作,所有值都为空:

addScriveCredentials: {
    method: 'POST',
    url: 'api/addcredentials/'

result.SalesId = user.SalesId;
userResource.addCredentials({}, { credentials: result }).$promise.then(function (data) {
    console.log(data);
});

C#:

[Route("addcredentials")]
[HttpPost]
public IHttpActionResult Addcredentials(Credentials credentials)
{
    return Ok(credentials);
}

【问题讨论】:

    标签: javascript c# angularjs


    【解决方案1】:

    您可以将一个对象作为帖子消息的正文传递。

    添加这样的类

    public class addCredentialObj
    {
        public int salesId { get; set; }
        public Credentials credentials { get; set; }
    }
    

    这样修改你的控制器(FromBody的使用可以阅读here

    [Route("addcredentials")]
    [HttpPost]
    public IHttpActionResult AddCredentials([FromBody]addCredentialObj obj)
    {
        return Ok(credentials);
    }
    

    在客户端中你需要为 addCredentialObj 类创建一个匹配的 json 对象

    var yourCredentials = {"ClientIdentifier":"a","ClientSecret":"b","TokenIdentifier":"c","TokenSecret":"d"};
    var jsonData = {
        salesId: yourId,
        credentials: yourCredentials
    };
    

    然后在对控制器的$http请求中,对json对象进行字符串化

    $http({
        method: 'POST',
        url: 'api/addcredentials',
        headers: {
            'Access-Control-Allow-Origin': '*',
            'Content-Type': 'application/json'
        },
        data: JSON.stringify(jsonData),
    });
    

    【讨论】:

    • 我在 URL 中发送一个参数,其余的是有效负载,在您上面的示例中,它就像在 URL 中添加一个参数一样?我以前可以使用 [FromBody] 来处理复杂对象,使用 [FromUri] 来处理 URL 参数中的简单类型,但由于某种原因它在这里不起作用。
    • @Ogglas 在您的控制器中,您没有指定它们是什么类型的参数,然后它只能传递一个参数,因为发布消息只能有一个正文。上次工作时,您是否传递了多个参数?你可以结合 [FromBody] 和 [FromUri] stackoverflow.com/questions/12072277/…
    • 是的,它会自动执行此操作。我尝试使用 [FromBody] 和 [FromUri] 但得到了相同的结果。 “默认情况下,Web API 使用以下规则绑定参数:如果参数是“简单”类型,Web API 会尝试从 URI 中获取值。简单类型包括 .NET 原始类型(int、bool、double、等等),加上 TimeSpan、DateTime、Guid、decimal 和 string,以及任何带有可以从字符串转换的类型转换器的类型。(稍后将详细介绍类型转换器。)对于复杂类型,Web API 会尝试读取值来自消息正文,使用媒体类型格式化程序。”
    • @Ogglas 好的,在您更新问题后,我认为在控制器端看起来没问题。您发送请求的内容类型是什么?
    【解决方案2】:

    我之前做过一个例子,希望下面的代码能帮助你理解。

    模型。

    using System.ComponentModel.DataAnnotations;
    
    public class ProductModel
    {
        public ProductModel(int id, string name, string category, decimal price)
        {
            Id = id;
            Name = name;
            Category = category;
            Price = price;
        }
    
        public int Id { get; set; }
    
        [Required]
        public string Name { get; set; }
    
        [Required]
        public string Category { get; set; }
    
        [Required]
        public decimal Price { get; set; }
    }
    

    ApiController。

    using Models;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Serialization;
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Web.Hosting;
    using System.Web.Http;
    
    public class ProductsController : ApiController
    {
        // other code omitted for brevity.
    
        [HttpPost]
        public IHttpActionResult PostProduct(ProductModel product)
        {
            try
            {
                if (product == null)
                {
                    throw new ArgumentNullException("Product parameter cannot be null");
                }
    
                if (ModelState.IsValid)
                {
                    // code omitted for brevity.
    
                    return this.Ok();
                }
                else
                {
                    throw new Exception("Product is invalid");
                }
            }
            catch (Exception ex)
            {
                return InternalServerError(ex);
            }
        }
    
        [HttpPut]
        public IHttpActionResult PutProduct(ProductModel product)
        {
            try
            {
                if (product == null)
                {
                    throw new ArgumentNullException("Product parameter cannot be null");
                }
    
                if (ModelState.IsValid && product.Id > 0)
                {
                    // code omitted for brevity.
    
                    return this.Ok();
                }
                else
                {
                    throw new Exception("Product is invalid");
                }
            }
            catch (Exception ex)
            {
                return InternalServerError(ex);
            }
        }
    
        // other code omitted for brevity.
    
    }
    

    Angular 服务。

    // products.js
    
    (function () {
        "use strict";
    
        angular
            .module("exampleApp")
            .constant("baseUrl", "http://localhost:53631/api/products/")
            .factory("productsResource", productsResource);
    
        productsResource.$inject = ["$resource", "baseUrl"];
    
        function productsResource($resource, baseUrl) {
            return $resource(baseUrl + ":id",
                {
                    id: "@id"
                },
                {
                    create: {
                        method: "POST"
                    },
                    save: {
                        method: "PUT"
                    }
                });
        }
    })();
    

    Angular 控制器。下面重点关注createProduct和updateProduct函数

    // edit.controller.js
    
    (function () {
        "use strict";
    
        angular
            .module("exampleApp")
            .controller("EditController", EditController);
    
        EditController.$inject = ["$routeParams", "$location", "productsResource"];
    
        function EditController($routeParams, $location, productsResource) {
            var vm = this;
            vm.currentProduct = null;
            vm.createProduct = createProduct;
            vm.updateProduct = updateProduct;
            vm.saveEdit = saveEdit;
            vm.cancelEdit = cancelEdit;
    
            if ($location.path().indexOf("/edit/") === 0) {
                var id = $routeParams.id;
                productsResource.get({ id: id }, function (data) {
                    vm.currentProduct = data;
                });
            }
    
            function cancelEdit() {
                $location.path("/list");
            }
    
            function updateProduct(product) {
                product.$save().then(function () {
                    $location.path("/list");
                });
            }
    
            function saveEdit(product) {
                if (angular.isDefined(product.id)) {
                    vm.updateProduct(product);
                } else {
                    vm.createProduct(product);
                }
    
                vm.currentProduct = {};
            }
    
            function createProduct(product) {
                new productsResource(product).$create().then(function (newProduct) {
                    $location.path("/list");
                });
            }
        }
    })();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-07-18
      • 2016-04-10
      • 2018-09-22
      • 1970-01-01
      • 2017-12-09
      • 1970-01-01
      • 1970-01-01
      • 2019-03-06
      相关资源
      最近更新 更多