2014-04-14 52 views
5

我在学习如何使用AngularJS的$资源来调用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; } 
} 

以下是我正在配置$资源:

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作为标准参数或该行为根本不执行。我不知道问题是在角度,网页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 $资源和网络API项目?

回答

9

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

Github Sample

型号粘合剂:

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

所以,如果我创建了$资源的新作用,这确实一个POST,把[FromUri]关该参数,将照顾它,而无需我创建一个自定义模型联编程序? – adam0101

+0

默认的模型联编程序在请求的主体中查找JSON。 '$ resource'是RESTful,并在查询字符串中发送JSON。不匹配的原因是您需要使用模型绑定器或使用'$ http'。 – Romoku

+0

等一下,我很困惑。根据文档,您可以使用'POST'方法在$ resource上指定新操作。你是说它忽略了它,并把它放在查询字符串呢? – adam0101