尝试保存实体时 ModelState.isvalid 为 false,错误表示相关实体中需要字段
Posted
技术标签:
【中文标题】尝试保存实体时 ModelState.isvalid 为 false,错误表示相关实体中需要字段【英文标题】:ModelState.isvalid is false when trying to save an entity, error says a field is required in a related entity 【发布时间】:2016-04-28 07:02:41 【问题描述】:我有这个代码来保存一个实体
public class TipoDeProducto
[Key]
[ScaffoldColumn(false)]
public int TipoDeProductoId get; set;
[Required]
[MaxLength(50, ErrorMessage = "El nombre debe tener como máximo 50 caractéres")]
public string Nombre get; set;
[Required]
public bool Estado get; set;
public virtual ICollection<Producto> Productos get; set;
和产品
public class Producto
[Key]
[ScaffoldColumn(false)]
public int ProductoId get; set;
public int TipoDeProductoId get; set;
[Required]
[MaxLength(50, ErrorMessage = "El nombre debe tener como máximo 50 caractéres")]
public string NombreProducto get; set;
[Required]
[DataType(DataType.MultilineText)]
[MaxLength(300, ErrorMessage = "La descripción debe tener como máximo 300 caractéres")]
public string Descripcion get; set;
public bool Estado get; set;
[ForeignKey("TipoDeProductoId")]
public virtual TipoDeProducto TipoDeProducto get; set;
编辑(POST)是这样的:
public HttpResponseMessage PutTipoDeProducto(int id, TipoDeProducto tipoDeProducto)
if (!ModelState.IsValid)
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
if (id != tipoDeProducto.TipoDeProductoId)
return Request.CreateResponse(HttpStatusCode.BadRequest);
try
unitOfWork.TipoDeProductoRepository.Update(tipoDeProducto);
unitOfWork.Save();
catch (DbUpdateConcurrencyException ex)
return Request.CreateErrorResponse(HttpStatusCode.NotFound, ex);
return Request.CreateResponse(HttpStatusCode.OK);
我的索引视图是这样的:
@model List<PowerData.Comisiones.Models.TipoDeProducto>
@using PowerData.Comisiones.Models
@
ViewBag.Title = "Tipos de producto";
<h2>Tipos de producto</h2>
@(html.Kendo().Grid<TipoDeProducto>()
.Name("Grid")
.Columns(columns =>
columns.Bound(p => p.Nombre).Title("Nombre");
columns.Bound(p => p.Estado).Title("Estado");
columns.Command(command => command.Edit(); );
)
.ToolBar(toolbar => toolbar.Create())
.Editable(editable => editable.Mode(GridEditMode.PopUp))
.Pageable()
.Sortable()
.Scrollable(scr => scr.Height(430))
.Filterable()
.DataSource(dataSource => dataSource
.WebApi()
//.Ajax()
//.ServerOperation(false)
.PageSize(20)
.Events(events => events.Error("error_handler"))
.Model(model =>
model.Id(p => p.TipoDeProductoId);
model.Field(p => p.TipoDeProductoId).Editable(false);
)
.Create(create => create.Url(Url.HttpRouteUrl("DefaultApi", new controller = "TipoDeProductos" ))) // Action invoked when the user saves a new data item
.Read(read => read.Url(Url.HttpRouteUrl("DefaultApi", new controller = "TipoDeProductos" ))) // Action invoked when the grid needs data
.Update(update => update.Url(Url.HttpRouteUrl("DefaultApi", new controller = "TipoDeProductos", id = "0" ))) // Action invoked when the user saves an updated data item
.Destroy(destroy => destroy.Url(Url.HttpRouteUrl("DefaultApi", new controller = "TipoDeProductos", id = "0" ))) // Action invoked when the user removes a data item
//.Create(update => update.Action("Create", "TipoDeCanales"))
//.Read(read => read.Action("Read", "TipoDeCanales"))
//.Update(update => update.Action("Edit", "TipoDeCanales"))
//.Destroy(update => update.Action("Delete", "TipoDeCanales"))
)
)
<script type="text/javascript">
function error_handler(e)
if (e.errors)
var message = "Errors:\n";
$.each(e.errors, function (key, value)
if ('errors' in value)
$.each(value.errors, function ()
message += this + "\n";
);
);
toastr.error(message)
//alert(message);
</script>
但是,在我添加项目之后,然后尝试编辑现有行,Model.Isvalid = false,当我检查验证错误时,它说 ProductName 是必需的,这甚至不是我表上的字段我正在尝试保存,它是一个相关的实体列表
【问题讨论】:
您能否在提交之前添加您的页面生成的 HTML,就像它看起来一样?由于您的 HTML 中的 ID 无效或不匹配,绑定可能存在问题。 【参考方案1】:我这样做是为了确保验证仅适用于当前实体:
foreach (var key in ModelState.Keys)
if (key.Split('.').Length > 2)
ModelState[key].Errors.Clear();
if (!ModelState.IsValid)
return BadRequest(ModelState);
检查.
的出现次数意味着:如果模型状态键类似于currentDTO.relatedDTO.field
,则忽略(清除)该验证错误。如果只是id
或currentDTO.validateThisField
之类的,则不会被清除。
【讨论】:
【参考方案2】:可能默认模型绑定器也在尝试绑定相关实体productos
。您可以使用 Bind
属性 ([Bind(Exclude="")]
) 来覆盖它,例如
public HttpResponseMessage PutTipoDeProducto(int id, [Bind(Exclude="productos")]TipoDeProducto tipoDeProducto)
//code here
【讨论】:
不工作,我检查了导航属性仍然绑定,所有属性都设置为0,null或空并且model.isvalid仍然是false 即使在设置了Bind
属性之后?这很奇怪,而且不可能。检查您是否在任何其他操作方法中使用相同的模型并且还排除相关实体。以上是关于尝试保存实体时 ModelState.isvalid 为 false,错误表示相关实体中需要字段的主要内容,如果未能解决你的问题,请参考以下文章
使用 MagicalRecord 保存实体 - 还尝试保存不同的实体?
Core Data Fetch 在插入实体时保存关系(同时)