我正在学习如何使用AngularJS的$资源来调用Web Api后端.我想在标准中传递对象层次结构并返回IEnumerable< Program>.以下是标准的示例:
$scope.criteria = { Categories:[ { Name: "Cat1",Options: [ {Text: "Opt1",Value: true},{Text: "Opt2",Value: false} ] },{ Name: "Cat2",Options: [ {Text: "Opt3",{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',Program: $resource('/api/program/:id',{ id: '@id' }) }; } ]);
我称之为:
api.Program.query({ criteria: $scope.criteria },function (response) { $scope.programs = response; });
无论我尝试什么,我都会得到null作为条件参数或者动作根本不执行.我不知道问题是在角度,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. } }
解决方法
您将需要一个自定义模型绑定器.从
what I understand起,FromUri将不会处理复杂的嵌套类型或json,其中$resource将放入查询字符串中.
型号粘合剂:
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",{ 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',method: 'POST',isArray: true } }); var program = new Program(); program.Categories = [ { Name: "Cat1",Value: false } ] } ]; $scope.submit = function () { console.log(program); program.$getByCriteria(); }; });