AngularJS - 将 REST 搜索端点映射到 $resource

Posted

技术标签:

【中文标题】AngularJS - 将 REST 搜索端点映射到 $resource【英文标题】:AngularJS - Mapping REST search endpoint onto $resource 【发布时间】:2014-10-24 00:20:25 【问题描述】:

ng-resource 返回一个具有以下默认资源操作的对象

   'get':    method:'GET',
    'save':   method:'POST',
    'query':  method:'GET', isArray:true,
    'remove': method:'DELETE',
    'delete': method:'DELETE' ;

我不确定从 AngularJS 的 REST WebApi 端点查询数据的最佳方法,但我已经在服务器端实现了 Predicate Builder 以便使用 Linq 查询我的数据库。我有一个名为“Search()”@/api/Product/Search 的(POST)端点,它将接受一个 searchCriteria JSON 对象,该对象被反序列化,馈送到 Linq 谓词构建器,并针对 dbContext 执行。我的 WebApi2 控制器的结构是这样的,使用新的路由属性功能:

  [RoutePrefix("Product")]
    public class ProductController : ApiController
    
        [HttpGet]
        [Route("")]
        public IEnumerable<Product> Get()
        
            try
            
                return _productBL.Get();
            
            catch
            
                throw new HttpResponseException(HttpStatusCode.InternalServerError);
            
        

        [HttpGet]
        [Route("productId")]
        public Product Get(string productId)
        
            try
            
                var product= _externalWorkStepBL.GetById(productId);
                if (product== null)
                
                    throw new HttpResponseException(HttpStatusCode.NotFound);
                
                return product;
            
            catch (Exception)
            
                throw new HttpResponseException(HttpStatusCode.InternalServerError);
            
        

        [HttpPost]
        public HttpResponseMessage Post([FromBody]Product product)
        
            try
            
                _productBL.Insert(product);
                var response = Request.CreateResponse(HttpStatusCode.Created, product);
                response.Headers.Location = new Uri(Request.RequestUri, string.Format("Product/0", product.workItemID));
                return response;
            
            catch
            
                throw new HttpResponseException(HttpStatusCode.BadRequest);
            
        

        [HttpPost]
        [Route("Search")]
        public IEnumerable<Product> Where([FromBody] SearchCriteria searchCriteria)
        
            if (searchCriteria == null || (searchCriteria.FieldContainsList == null || searchCriteria.FieldEqualsList == null || searchCriteria.FieldDateBetweenList == null))
            
                throw new HttpRequestException("Error in, or null, JSON");
            
            return _productBL.Where(searchCriteria);
        

        [HttpPut]
        [Route("")]
        public HttpResponseMessage Put([FromBody]Productproduct)
        
            try
            
                _productBL.Update(product);
                var response = Request.CreateResponse(HttpStatusCode.OK);
                response.Headers.Location = new Uri(Request.RequestUri, string.Format("Product/0", product.Id));
                return response;
            
            catch ()
            
                throw new HttpResponseException(HttpStatusCode.InternalServerError);
            
        

        [HttpDelete]
        [Route("productId")]
        public void Delete(string productId)
        
            HttpResponseMessage response;
            try
            
                _productBL.Delete(productId);
                response = new HttpResponseMessage(HttpStatusCode.NoContent);
                response.Headers.Location = new Uri(Request.RequestUri, string.Format("Product/"));    
            
            catch (Exception)
            
                throw new HttpResponseException(HttpStatusCode.InternalServerError);
            
        
    

在客户端,我将 $resource 包装在一个名为 $myResource 的工厂中,并添加了一个 PUT 方法。然后我将 $myResource 用于我的其他工厂,如下所示:

var app = angular.module('App', ['ngResource'])  
    .factory('$myResource', ['$resource', function ($resource) 
    return function (url, paramDefaults, actions) 
        var MY_ACTIONS = 
            'update':  method: 'PUT'       
        ;
        actions = angular.extend(, MY_ACTIONS, actions);
        return $resource(url, paramDefaults, actions);
    
])
    .service('ProductFactory', ['$myResource', function ($myResource) 
        return $myResource('/api/Product/:productId')
    ]);

这很好用,但现在我想添加我的搜索端点。 Angular documentation for ng-Resource 声明可以在操作方法中覆盖 url,但我不清楚如何执行此操作。我可以将“搜索”操作添加到 $myResource,但是如何修改 ProductFactory 中的 url?

 .factory('$myResource', ['$resource', function ($resource) 
        return function (url, paramDefaults, actions) 
            var MY_ACTIONS = 
                'update':  method: 'PUT' ,        
                'search':  method: 'POST','params':  searchCriteria: '@searchCriteria' , isArray: true    
            ;
            actions = angular.extend(, MY_ACTIONS, actions);
            return $resource(url, paramDefaults, actions);
        
    ])  

按照目前的情况,调用 ProductFactory.search(searchCriteria) 会发送一个带有正确 JSON 的 POST 请求,但会发送到错误的 URL“/api/Product”。我需要它发布到“/api/Product/Search”。如何修改 $myResource 以使用“api/xxx/Search”,其中 xxx 是控制器名称?

【问题讨论】:

【参考方案1】:

没关系!没想到这会奏效,但确实如此。

.factory('$myResource', ['$resource', function ($resource) 
            return function (url, paramDefaults, actions) 
                var searchUrl = url + "/Search/:searchCriteria"
                var MY_ACTIONS = 
                    'update':  method: 'PUT' ,        //add update (PUT) method for WebAPI endpoint 
                    'search':  method: 'POST', url : searchUrl,'params':  searchCriteria: '@searchCriteria' , isArray: true      //add Search (POST)
                ;
                actions = angular.extend(, MY_ACTIONS, actions);
                return $resource(url, paramDefaults, actions);
            
        ])    

【讨论】:

以上是关于AngularJS - 将 REST 搜索端点映射到 $resource的主要内容,如果未能解决你的问题,请参考以下文章

命名用于编译/映射/处理数据的 REST 端点

Spring Boot REST API 端点映射最佳实践

Wordpress 使用自定义端点 rest api 上传多个图像(离子作为最终用户)

将AngularJS应用程序与WSO2身份服务器集成

从 AngularJS 前端到 Spring rest 后端的 CORS 问题

使用新的 REST API 应用程序从经典(IPN 端点)搜索 Paypal 交易