【问题标题】:Working example of AngularJS $resource searching items in Web ApiAngularJS $resource 在 Web Api 中搜索项目的工作示例
【发布时间】:2014-05-28 15:22:28
【问题描述】:

我正在学习如何使用 AngularJS 的 $resource 来调用 Web Api 后端。我想将对象层次结构作为标准传递并取回IEnumerable<Program>。以下是条件示例:

$scope.criteria = {
    Categories:[
        {
            Name: "Cat1",
            Options: [
                {Text: "Opt1", Value: true},
                {Text: "Opt2", Value: false}
            ]
        },
        {
            Name: "Cat2",
            Options: [
                {Text: "Opt3", Value: true},
                {Text: "Opt4", Value: false}
            ]
        }
    ]
}

我在服务器上用 C# 定义了相同的对象。

public class CriteriaModel
{
   public IEnumerable<CriteriaCategory> Categories { get; set; }
}

public class CriteriaCategory
{
    public string Name { get; set; }
    public IEnumerable<CriteriaOption> Options { get; set; }
}

public class CriteriaOption
{
    public string Text { get; set; }
    public bool Value { get; set; }
}

这是我配置 $resource 的方式:

angular.module('my.services')
    .factory('api', [
        '$resource',
        function ($resource) {
            return {
                Profile: $resource('/api/profile/:id', { id: '@id' }),
                Settings: $resource('/api/settings/:id', { id: '@id' }),
                Program: $resource('/api/program/:id', { id: '@id' })
            };
        }
    ]);

我这样称呼它:

api.Program.query({ criteria: $scope.criteria }, function (response) {
    $scope.programs = response;
});

无论我尝试什么,要么得到null 作为标准参数,要么根本不执行操作。我不知道问题出在 angular、web api 还是两者兼而有之。这是操作:

public class ProgramController : ApiController
{
    public IEnumerable<Program> GetByCriteria([FromUri]CriteriaModel criteria)
    {
        // Either criteria is null or this action doesn't even get
        // executed depending on what I try.
    }
}

有人可以帮我找到一个使用 AngularJS $resource 和 Web Api 搜索和返回项目的工作示例吗?

【问题讨论】:

    标签: c# angularjs asp.net-web-api ngresource


    【解决方案1】:

    您将需要一个自定义模型绑定器。从what I understand FromUri 将不会处理复杂的嵌套类型或$resource 将放入查询字符串的json。

    模型绑定器:

    public class CriteriaModelBinder : IModelBinder
    {
        public bool BindModel(
            HttpActionContext actionContext,
            ModelBindingContext bindingContext
        )
        {
            if (bindingContext.ModelType != typeof (CriteriaModel))
            {
                return false;
            }
    
            var value = bindingContext.ValueProvider.GetValue("Categories");
    
            if (value == null)
            {
                return false;
            }
    
            var categoryJson = value.RawValue as IEnumerable<string>;
    
            if (categoryJson == null)
            {
                bindingContext.ModelState.AddModelError(
                    bindingContext.ModelName, "Categories cannot be null.");
                return false;
            }
            
            var categories = categoryJson
                .Select(JsonConvert.DeserializeObject<CriteriaCategory>)
                .ToList();
    
            bindingContext.Model = new CriteriaModel {Categories = categories};
            return true;
        }
    }
    

    控制器:

    [RoutePrefix("api/program")]
    public class ProgramController : ApiController
    {
        [Route("getbycriteria")]
        [HttpGet]
        public HttpResponseMessage GetByCriteria(
            [ModelBinder(typeof(CriteriaModelBinder))]CriteriaModel criteria
        )
        {
            return new HttpResponseMessage(HttpStatusCode.OK);
        }
    }
    

    角度控制器:

    angular.module('myApp').
        controller('HomeController', function($scope, $resource) {
            var Program = $resource('/api/program/:id', {}, {
                getByCriteria: {
                    url: '/api/program/getbycriteria',
                    method: 'GET',
                    isArray: true
                }
            });
    
            var program = new Program();
            var criteria = {
                Categories: [
                    {
                        Name: "Cat1",
                        Options: [
                            { Text: "Opt1", Value: true },
                            { Text: "Opt2", Value: false }
                        ]
                    },
                    {
                        Name: "Cat2",
                        Options: [
                            { Text: "Opt3", Value: true },
                            { Text: "Opt4", Value: false }
                        ]
                    }
                ]
            };
    
            $scope.submit = function () {
                console.log(program);
                program.$getByCriteria(criteria);
            };
        });
    

    编辑:

    这里是POST

    控制器:

    [RoutePrefix("api/program")]
    public class ProgramController : ApiController
    {
        [Route("getbycriteria")]
        [HttpPost]
        public HttpResponseMessage GetByCriteria(CriteriaModel criteria)
        {
            return new HttpResponseMessage(HttpStatusCode.OK);
        }
    }
    

    角度:

    angular.module('myApp').
        controller('HomeController', function($scope, $resource) {
            var Program = $resource('/api/program/:id', {}, {
                getByCriteria: {
                    url: '/api/program/getbycriteria',
                    method: 'POST',
                    isArray: true
                }
            });
    
            var program = new Program();
            program.Categories = [
                    {
                        Name: "Cat1",
                        Options: [
                            { Text: "Opt1", Value: true },
                            { Text: "Opt2", Value: false }
                        ]
                    },
                    {
                        Name: "Cat2",
                        Options: [
                            { Text: "Opt3", Value: true },
                            { Text: "Opt4", Value: false }
                        ]
                    }
                ];
    
            $scope.submit = function () {
                console.log(program);
                program.$getByCriteria();
            };
        });
    

    【讨论】:

    • 因此,如果我在 $resource 中创建了一个新操作,该操作执行 POST 并将 [FromUri] 从参数中移除,是否可以在无需创建自定义模型绑定器的情况下处理它?
    • 默认模型绑定器在请求正文中查找 JSON。 $resource 是 RESTful 并在查询字符串中发送 JSON。不匹配是您需要使用模型绑定器或使用 $http 的原因。
    • 等等,我很困惑。您可以根据文档使用“POST”方法在 $resource 上指定新操作。您是说它忽略了这一点并将其放在查询字符串中吗?
    • 是的,您可以将操作更改为POST,除非您需要将Categories 直接附加到program 对象。
    • 我建议不要使用POST,除非您打算进行有副作用的操作。
    猜你喜欢
    • 2012-10-27
    • 2016-12-10
    • 2016-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多