我有一个Web API(2)项目,它有部门和员工。一个员工有一个部门,一个部门有一个员工列表。
现在,在前端,当创建或编辑员工时,用户必须选择一个部门。当将其发布到API时,部门包含员工列表(这会导致无效的模型状态),如何防止这种情况发生?
这是我的相关设置:
型号:
public class Employee : IEntity, ICreatedOn, IModifiedOn, IMappable
{
[Key]
public virtual int Id { get; set; }
public virtual Department Department { get; set; }
// .. other properties
}
public class Department : IEntity, IMappable
{
[Key]
public virtual int Id { get; set; }
public virtual ICollection<Employee> Employees { get; set; }
// .. other properties
}
Web API控制器:
public class EmployeesController : ApiController
{
private readonly IEmployeeService _employeeService;
public EmployeesController(IEmployeeService employeeService)
{
this._employeeService = employeeService;
}
// .. GET, POST, DELETE etc.
// PUT: api/Employees/5
[ResponseType(typeof(void))]
public IHttpActionResult PutEmployee(int id, EmployeeVM employee)
{
// This is always invalid, because the employee has a department, which in turn has a list of employees which can be invalid
// What to do to exclude the list of employees from validation, or even better prevent from being sent to the API
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
// Update etc..
return StatusCode(HttpStatusCode.NoContent);
}
Angular(DataService.js):
app.factory('DataService',
["$http",
function ($http) {
return {
// other functions
updateEmployee: _updateEmployee
}
function _updateEmployee(employee) {
// Maybe exclude the list of employees in employee.department in here??
return $http.put(employeesUrl + "/" + employee.id, employee);
}
// .. other functions
}]);
注:
- 它发生在Put和Post中(更新和创建)
- 我正在使用AutoMapper映射到ViewModels,它们看起来与实体相同
- 我正在为ORM使用实体框架
我尝试过的:
- Employees集合的[JsonIgnore]属性;这导致在加载部门时也不会加载员工
- 控制器操作参数中的[Bind(Exclude="Employees")]属性,这没有任何效果
- [绑定(排除="部门.员工")]相同
什么是有效的,但我相信一定有更好的解决方案:
function _updateEmployee(employee) {
var newEmp = angular.copy(employee);
delete newEmp.department.employees;
return $http.put(employeesUrl, newEmp);
}
创建一个用于更新employee
的新请求。类似:
public class UpdateEmployeeRequest{
public int EmployeeId {get;set;}
public int DepartmentId {get;set;}
//and so on
}
对于此请求,您可以指定具体的验证。
并使用显式ID声明实体:
public class Employee : IEntity, ICreatedOn, IModifiedOn, IMappable
{
[Key]
public int Id { get; set; }
[ForeignKey( "Department" )]
public Guid DepartmentId { get; set; }
[Required]
public virtual Department Department { get; set; }
// .. other properties
}
我会像这个一样修改Employee实体
public class Employee : IEntity, ICreatedOn, IModifiedOn, IMappable
{
[Key]
public virtual int Id { get; set; }
//Add DepartmentId
public Guid? DepartmentId { get; set; }
public virtual Department Department { get; set; }
// .. other properties
}
然后你只能设置DepartmentId,就这样了。EF将负责剩下的