【发布时间】:2018-03-30 05:23:48
【问题描述】:
我有一个带有子对象列表的模型。我创建了一个自定义验证属性,在模型上实现了 IValidatableObject,并且我收到了预期的错误消息。问题是,一旦属性在模型状态中出现错误,我就无法将更新的值发回服务器。在点击提交按钮和在控制器中接收模型之间的一段时间内,它们会被清除。
如果我在控制器操作中调用 ModelState.Clear(),我不会收到任何消息,但新值会按预期发布。然而,模型正在使用自定义属性,因为 ModelState.IsValid == false
我认为处理这个问题的最好方法是在 $(ready) 之后以某种方式在客户端上调用 ModelState.Clear() 以便我获得验证消息,但也可以将更改后的值发布到服务器。这是可能的还是有更好的方法来做到这一点?
父模型
public class PayrollPlanModel : IMapFrom<Data.PayrollPlan>
{
public int? PayrollPlanId { get; set; }
[Required]
public string Name { get; set; }
public List<PlanOptionFormModel> Options { get; set; }
}
具有自定义属性的父级模型列表属性
public class PlanOptionFormModel : IValidatableObject
{
public int PlanOptionValueId { get; set; }
public int PayrollPlanId { get; set; }
public string PlanName { get; set; }
public int PlanOptionId { get; set; }
public string Description { get; set; }
[UIHint("_Money")]
[RequiredIf("Selected", true)]
public decimal? Value { get; set; }
public bool Selected { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (Selected && !Value.HasValue)
{
yield return new ValidationResult("Add a value.");
}
}
}
自定义属性(无耻地从这里偷走)
public class RequiredIfAttribute : ValidationAttribute
{
RequiredAttribute _innerAttribute = new RequiredAttribute();
public string _dependentProperty { get; set; }
public object _targetValue { get; set; }
public RequiredIfAttribute(string dependentProperty, object targetValue)
{
this._dependentProperty = dependentProperty;
this._targetValue = targetValue;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var field = validationContext.ObjectType.GetProperty(_dependentProperty);
if (field != null)
{
var dependentValue = field.GetValue(validationContext.ObjectInstance, null);
if ((dependentValue == null && _targetValue == null) || (dependentValue.Equals(_targetValue)))
{
if (!_innerAttribute.IsValid(value))
{
string name = validationContext.DisplayName;
return new ValidationResult(ErrorMessage = name + " Is required.");
}
}
return ValidationResult.Success;
}
else
{
return new ValidationResult(FormatErrorMessage(_dependentProperty));
}
}
}
页面sn-p
for (int i = 0; i < Model.Options.Count; i++)
{
<div class="row">
<div class="col-md-3">
@Html.HiddenFor(m => Model.Options[i].PlanOptionValueId)
@Html.HiddenFor(m => Model.Options[i].PayrollPlanId)
@Html.HiddenFor(m => Model.Options[i].PlanOptionId)
@Html.HiddenFor(m => Model.Options[i].Description)
</div>
<div class="col-md-1 text-right">
@Html.CheckBoxFor(m => Model.Options[i].Selected, new { @data_textbox = "optionValue_" + i.ToString(), @class = "form-control modelOptionSelector" })
</div>
<div class="col-md-2 text-right">
<h4>@Model.Options[i].Description</h4>
</div>
<div class="col-md-1">
@Html.EditorFor(m => Model.Options[i].Value, Model.Options[i].Selected ? new { HtmlAttributes = new { id = "optionValue_" + i.ToString(), @class = "planOptionValueEditor" } } : (object)new { HtmlAttributes = new { disabled = "disabled", id = "optionValue_" + i.ToString(), @class = "planOptionValueEditor" } })
@Html.ValidationMessageFor(m => Model.Options[i].Value)
</div>
</div>
}
<br />
编辑器模板
@model decimal?
@{
var defaultHtmlAttributesObject = new { };
var htmlAttributesObject = ViewData["htmlAttributes"] ?? new { };
var htmlAttributes = Html.MergeHtmlAttributes(htmlAttributesObject, defaultHtmlAttributesObject);
string attemptedValue = "";
ModelState modelStateForValue = Html.ViewData.ModelState[Html.IdForModel().ToString()];
if (modelStateForValue != null)
{
attemptedValue = modelStateForValue.Value.AttemptedValue;
}
}
@(Html.Kendo().CurrencyTextBoxFor(m => m)
.HtmlAttributes(htmlAttributes)
.Format("c")
.Spinners(false)
)
控制器
[HttpPost]
public ActionResult EditPlan(PayrollPlanModel model)
{
if(ModelState.IsValid)
{
}
else
{
}
return View(model);
}
【问题讨论】:
-
ModelState是服务器端 - 从客户端调用它是没有意义的。你声称的没有意义。显示您的代码并解释问题所在。 -
我添加了代码。你不明白的问题怎么办?一旦错误被添加到视图状态,该属性将不会将任何更新的值发布到控制器。我试图想一个更好的方法来解释它。给我一分钟
-
一开始您似乎并不了解客户端和服务器端代码之间的区别。而且您不应该使用
IValidatable对象(这不会提供客户端验证,您的RequiredIfAttribute也不会,因为您还没有实现IClientValidatable。给我一个机会来尝试并根据您的编辑。 -
我理解他们很好。谢谢。我不明白为什么当添加模型状态错误时,该值停止发布到服务器也不是没有的,但一旦我实现了接口,那就是错误消息开始出现在客户端上的时候。耸耸肩
-
实际上您可能对界面是正确的。客户端消息不是客户端返回的消息
标签: asp.net-mvc