AngularJS — сопоставление конечной точки поиска REST с $ресурсом

ng-resource возвращает объект со следующими действиями ресурса по умолчанию

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

Я не уверен, что это лучший метод для запроса данных из конечных точек REST WebApi из AngularJS, но я реализовал на стороне сервера Predicate Builder, чтобы запрашивать мою базу данных с помощью Linq. У меня есть конечная точка (POST) с именем «Search()» @/api/Product/Search, которая будет принимать объект 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 для ng-Resource указано, что URL-адрес может быть переопределен в метод действия, но мне непонятно, как это сделать. Я могу добавить действие «поиск» в $myResource, но как мне изменить URL-адрес в ProductFactory?

 .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) отправляет запрос POST с правильным JSON, но с неправильным URL-адресом «/api/Product». Мне нужно, чтобы он публиковался в "/api/Product/Search". Как я могу изменить $myResource для использования «api/xxx/Search», где xxx — это имя контроллера?


person JM.    schedule 29.08.2014    source источник


Ответы (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);
            }
        }])    
person JM.    schedule 29.08.2014