【问题标题】:Angular Web API PUT Model Not RecognisedAngular Web API PUT 模型无法识别
【发布时间】:2016-05-19 12:42:10
【问题描述】:

我无法使用 Angular 将相当复杂的数据模型放入 Web API 控制器。

这是我们目前所拥有的:

角度控制器:

$scope.saveDelivery = function () {
    var val = $('#run-value', $element)[0].value;
    console.info("Batsman: " + $scope.striker.Name + ", Shot: " + $scope.shot + " for " + val + " runs. ");

    if ($scope.game.Overs[$scope.over - 1].Deliveries == null) {
        $scope.game.Overs[$scope.over - 1].Deliveries = [];
    }

    console.info("Over: " + $scope.over + ", Delivery: " + $scope.delivery);
    if ($scope.delivery > 6) {
        $scope.over++;
        $scope.delivery = 1;
    }
    else {
        $scope.delivery++;
    }

    if ($scope.striker == undefined) {
        alert("No batsman selected");
    }
    else {

        var shot = {};

        shot.Id = 0;
        shot.Runs = $scope.runs;
        shot.Stroke = $scope.shot;
        if ($scope.runs == -5) {
            shot.Dismissal = $scope.shot;
        }
        else {
            shot.Dismissal = null;
        }

        var delivery = {};
        delivery.Id = 0;
        delivery.Number = $scope.delivery;
        delivery.Batter = $scope.striker;
        delivery.Bowler = $scope.nonstriker;
        delivery.Shot = shot;


        $scope.game.Overs[$scope.over - 1].Deliveries.push(delivery);
        console.info($scope.game);

        $http.put('/api/games/:id', { id: $scope.game.Id, game: $scope.game }).success(function (data, status, headers, config) {
            console.info(data);
        });
        //$http.post('/score/testing', { Test: "This is a test" }).success(function (data, status, headers, config) {
        //    console.info(data);
        //});
    }
}

API 控制器:

// PUT: api/Games/5
[HttpPut("{id}")]
public IActionResult PutGame(int id, [FromBody] Game game)
{
    if (!ModelState.IsValid)
    {
        return HttpBadRequest(ModelState);
    }
    ... etc...

我在 Fiddler 中获取的原始 JSON 数据如下所示(抱歉格式化):

{"id":1,"game":{"Id":1,"Date":"2016-04-20T20:30:00","Team":{"Id":"a5abca2a-0e05-11e6-8596-4f0c9eb370be","Name":"Yellow Duckies","Players":null},"Opposition":"Miller Studios","Overs":[{"Id":1,"Number":1,"Innings":0,"Deliveries":[{"Id":0,"Number":2,"Batter":{"Id":"1a903e4a-0f8a-11e6-99ad-b3c19db370be","Email":"phil@email.address.here","Name":"Phil"},"Bowler":{},"Shot":{"Id":0,"Runs":2,"Stroke":2,"Dismissal":null}}]},{"Id":2,"Number":2,"Innings":0,"Deliveries":null},{"Id":3,"Number":3,"Innings":0,"Deliveries":null},{"Id":4,"Number":4,"Innings":0,"Deliveries":null},...

如果我将 Web API PUT 参数更改为纯 object,它会很好地拾取主体,所以我猜测对象的解析方式存在问题,但如果我能,我该死看看问题出在哪里。这是 C# 模型:

namespace IndoorCricket.Models
{
    public enum Innings { Batting, Bowling }

    public class Game
    {
        public int Id { get; set; }
        public DateTime Date { get; set; }
        public virtual Team Team { get; set; }
        public string Opposition { get; set; }

        public virtual ICollection<Over> Overs { get; set; }
    }


    public class Over
    {
        public int Id { get; set; }
        public int Number { get; set; }
        public Innings Innings { get; set; }

        //public virtual Game Game { get; set; }
        public virtual ICollection<Delivery> Deliveries { get; set; }
    }

    public class Delivery
    {
        public int Id { get; set; }
        public int Number { get; set; }
        public virtual Shot Shot { get; set; }

        public virtual Player Bowler { get; set; }
        public virtual Player Batter { get; set; }
    }

    public class Shot
    {
        public int Id { get; set; }
        public int Runs { get; set; }
        public Stroke Stroke { get; set; }
        public Dismissal Dismissal { get; set; }
    }

    public enum Stroke
    {
        Out     = -5,
        Dotball = 0,
        Single  = 1,
        Two     = 2,
        Three   = 3,
        Four    = 4,
        Five    = 5,
        Seven   = 7
    }

    [Flags]
    public enum Dismissal
    {
        Caught  = 1,
        Bowled  = 2,
        Runout  = 4,
        Stumped = 8,
        Mankad  = 16,
        LBW     = 32
    }
}

谁有更好的眼睛可以发现问题?

【问题讨论】:

  • ...并为相当粗糙的代码提前道歉。里面有很多调试/测试的东西需要稍后清理。
  • 你能快点试试吗? $http.put('/api/games/' + $scope.game.Id, { game: $scope.game }).suc...
  • @EduardUta ID 仍会正常获取,但 Game 参数仍填充空值。实际上,该参数与新初始化的对象相同。所有 int 值为零,子集合为 null。
  • 嗯,我认为 $scope 的天线没有到达您将其用于游戏对象的位置。在调用之前,创建一个新的游戏对象(来自 $scope.game)并在调用中使用新对象.. { game: newGameObj }))。
  • 控制器期望的是游戏,而不是包含游戏的东西,不是吗?

标签: angularjs json asp.net-web-api2


【解决方案1】:

它试图从主体构建的game 类不是根对象。 .NET 将检测到 id 列,并且无法映射到类 Game。您能否将 JSON 中的 game 设为根?既然您似乎将“id”传递到 API 的控制器端点?

另外,您的 TeamPlayer 类在哪里指定?

【讨论】:

  • 我尝试将方法更改为 [HttpPut] 的装饰,而实际方法只是简单地获取一个游戏对象:public IActionResult PutGame([FromBody] Game game) 但这没有区别。我本来希望 .Net 能够识别路由中的 ID,并且无论如何都会在正文中传递一个单独的参数。
【解决方案2】:

最终通过将 API 参数类型从强类型的“游戏”对象更改为普通的 object 解决了这个问题。从那里,我使用 JSON.Net 反序列化对象并检查发送的内容。

因为我的嵌套 JSON 对象具有合理的深度,我可以看到一个期望值的属性被传递给它,而不是 null。

我暂时就这样(虽然感觉很恶心,我会想进一步解决这个问题):

    public IActionResult PutGame(int id, [FromBody] object game)
    {
        JObject obj = JsonConvert.DeserializeObject<JObject>(game.ToString());
        Game g = obj.Root.First.Value<JToken>().First.ToObject<Game>();
    ...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-12-12
    • 2020-10-17
    • 1970-01-01
    • 1970-01-01
    • 2020-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多