AngularJS $resource 在 Web Api 中搜索项目的工作示例

Posted

技术标签:

【中文标题】AngularJS $resource 在 Web Api 中搜索项目的工作示例【英文标题】:Working example of AngularJS $resource searching items in 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 搜索和返回项目的工作示例吗?

【问题讨论】:

【参考方案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,除非您打算进行有副作用的操作。

以上是关于AngularJS $resource 在 Web Api 中搜索项目的工作示例的主要内容,如果未能解决你的问题,请参考以下文章

AngularJS:具有嵌套资源的 $resource

了解 AngularJS 的 $resource

angularjs $resource 类级回调,或后处理

如何在 AngularJS $resource 中使用路径变量而不是请求参数

如何使用 AngularJS 的 $resource 和 spring rest 控制器获取布尔值

AngularJS $resource GET 中的多个参数