2014-04-14 11 views
5

Uczę się, jak korzystać z zasobów $ AngularJS, aby wywoływać backend Web Api. Chcę przekazać hierarchię obiektów jako kryteria i odzyskać IEnumerable<Program>. Oto przykład kryteriów:

$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} 
      ] 
     } 
    ] 
} 

Mam te same obiekty zdefiniowane na serwerze w języku 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; } 
} 

Oto jak ja konfigurowania $ 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' }) 
      }; 
     } 
    ]); 

A ja nazywam to tak:

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

Bez względu na to, co staram I albo dostać null jako parametr kryteriów lub akcja w ogóle nie działa. Nie wiem, czy problem jest w kanciastym, web api, czy w obu. Oto działanie:

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. 
    } 
} 

Czy ktoś może mi pomóc dostać pracy przykład idzie do wyszukiwania i powrocie elementów za pomocą angularjs $ zasobów i Web API?

Odpowiedz

9

Będziesz potrzebować niestandardowego segregatora. Od what I understandFromUri nie będzie obsługiwać złożonych typów zagnieżdżonych lub json, które $resource wstawi do łańcucha zapytania.

Github Sample

modelu spoiwo:

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; 
    } 
} 

Kontroler:

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

kątowe Kontroler:

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); 
     }; 
    }); 

Edycja:

Oto dla POST:

Kontroler:

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

kątowa:

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(); 
     }; 
    }); 
+0

więc jeśli stworzył nową akcję w $ zasobu, który robi POST i zabrał [FromUri] off parametr, czy to zajmie się tym bez konieczności tworzenia niestandardowego spoiwa modelu? – adam0101

+0

Domyślny segregator modelu szuka JSON w treści żądania. '$ resource' jest RESTful i wysyła JSON w ciągu zapytania. Niezgodność polega na tym, że musisz użyć segregatora modelowego lub użyć '$ http'. – Romoku

+0

Czekaj, jestem zdezorientowany. Możesz określić nową akcję na $ resource za pomocą metody "POST" zgodnie z dokumentacją. Mówisz, że to ignoruje i umieszcza to w querystring? – adam0101

Powiązane problemy