问题 - 我的任务是在MVC中复制旧的Web窗体应用程序。我被要求保持标记类似。我不知道为什么,但你去了。那么,一般来说简单的标签和文本框会变成
<td>
<table style="width: 100%;">
<tr>
<td>
<span id='@Model.Label' class='MILabel'>
@Model.Name
</span>
</td>
<td class="NoWrap">
<span id='@Model.Prefix' class='Prefix'>@Model.Prefix</span>
</td>
</tr>
</table>
</td>
<td class="SetDivInputWidth">
<div id='@Model.DivId' class="NoWrap">
@Html.TextAreaFor(m => m.Value, new
{
@id = Model.Name,
@onkeyup = Model.OnKeyUp,
@class = Model.FullClass,
@maxlength = "100"
}.DisabledIf(Model.IsDisabled))
@{
if (Model.HasGuidanceNote)
{
<img class="GuidanceNote" src='~/Content/Images/info.png' alt='Notes'
onmouseover="@Model.GuidanceNotesMouseOver"
onmouseout="@Model.GuidanceNotesMouseOut" />
<span id="@Model.GuidanceNotesIdentifier" class='Info'>@Model.GuidanceNote</span>
}}
<img class="ErrorIcon" alt='' src='@Model.ErrorImage' id="@Model.ErrorImageId" onmouseover="@Model.ErrorImageMouseOver" onmouseout="@Model.ErrorImageMouseOut" />
<div class="WarningText" id="@Model.WarningDivId"></div>
</div>
</td>
这是一个用于
基本实现的自定义EditorTemplatepublic class MyTextField
{
public virtual string Name { get; set; }
private bool _isReadOnly;
public string Label
{
get { return Name + "Label"; }
}
public string Value { get; set; }
public string Prefix { get; set; }
public string CssClass { get; set; }
public string FullClass
{
get { return CssClass + " " + Readonly; }
}
public string Readonly
{
get
{
return _isReadOnly ? "MIReadOnly" : String.Empty;
}
}
public string Disabled { get; set; }
public bool IsDisabled { get; set; }
public bool HasGuidanceNote
{
get { return (GuidanceNote != null); }
}
public bool IsReadonly
{
get { return _isReadOnly; }
set
{
_isReadOnly = value;
}
}
public string OnKeyUp
{
get { return "Fields.callOnChange('" + Name + "');"; }
}
public string ErrorImage { get; set; }
public string ErrorImageId
{
get { return Name + "ErrorIcon"; }
}
public string ErrorImageMouseOver
{
get { return "Utils.showErrorText('" + Name + "')"; }
}
public string ErrorImageMouseOut
{
get { return "Utils.clearErrorText('" + Name + "')"; }
}
public string DivId
{
get { return Name + "Div"; }
}
public string WarningDivId
{
get { return Name + "ErrorText"; }
}
public string GuidanceNote { get; set; }
public string GuidanceNotesIdentifier
{
get { return Name + "GuidanceNotes"; }
}
public string GuidanceNotesMouseOver
{
get { return "Utils.showGuidanceNote('" + GuidanceNotesIdentifier + "')"; }
}
public string GuidanceNotesMouseOut
{
get { return "Utils.clearGuidanceNote('" + GuidanceNotesIdentifier + "')"; }
}
}
这一切都很好。事实上,它很棒。
由于各个领域的复杂验证,问题出现了。显然,我必须在视图模型中创建MyTextField的实例(而不是它的真实名称),填充编辑器的相关字段,然后使用EditorTemplate显示。
但我无法使用DataAnnotations来验证我的数据,因为每个MyTextBox都有不同的验证规则。有些可能是必填字段,有些可能不是。有些只允许某些输入,有些则根本没有验证。 Som依赖于同一个视图中的其他字段 - 其他人不会。
有没有人有任何建议,或者我是否应该让自己手动使用JavaScript手动验证所有内容?
感谢阅读。
答案 0 :(得分:0)
是的你可以使用Jquery, 在表单加载时,此脚本将向首选字段添加验证
<script>
$(document).ready(function () {
$('#yourId').rules("add", { required: true,messages:{required:"This is required field"} });
});
</script>
如果您要删除任何事件的任何验证,请使用
$('#yourId').rules("remove");
希望这有帮助!
答案 1 :(得分:0)
这个问题有很多可能的解决方案,你如何处理它取决于很多因素。
首先,如果您不需要客户端验证,您始终可以在模型上实现IValidatableObject并进行自定义验证。这很简单直接,但不能提供非常好的最终用户体验。
另一种选择是使用类似FluentValidation的东西,它允许你编写自定义验证器。
另一个选择是编写自定义DataAttributes,它们实现自己的客户端验证接口。您还必须包含一些自定义JavaScript来配置验证器。
另一个选项是简化操作,并为每个方案创建包含数据属性的自定义视图模型。如果选项的数量很大,这可能会很快变得混乱,但如果它是可管理的,这是一个相对简单的解决方案。
还有一些方法需要深入挖掘框架,我不会进入这里......但我认为你明白了......你必须决定如何进行验证并找出最佳方法。
答案 2 :(得分:0)
好吧,我找到了一个我非常满意的答案。
这是我的一个显示类,我使用隐式运算符使其有效地成为字符串。
public class RubikTextBox : AbstractField, IAbstractField
{
public RubikTextBox(string val)
{
Value = val;
}
public static implicit operator string(RubikTextBox stringValue)
{
return stringValue.ToString();
}
public static implicit operator RubikTextBox(string stringValue)
{
return new RubikTextBox(stringValue);
}
public override string ToString()
{
return Value;
}
}
它继承了一些包含其他属性的东西,抽象类特别用于吐出div ID和东西,通常可以节省我的时间和代码。
现在,为这个野兽发布HTML的EditorTemplate看起来像这样 -
<td>
<table style="width: 100%;">
<tr>
<td>
<span id='@Model.LabelName' class='MILabel'>
@Model.Label
</span>
</td>
<td class="NoWrap">
<span id='@Model.PrefixName' class='Prefix'>@Model.Prefix</span>
</td>
</tr>
</table>
</td>
<td class="SetDivInputWidth">
<div id='@Model.DivId' class="NoWrap">
@Html.TextBoxFor(m => m, new
{
id = Model.Name,
@class = Model.CssClass,
maxlength = "100"
}.DisabledIf(Model.IsDisabled).ReadOnlyIf(Model.IsReadonly))
@{
if (Model.HasGuidanceNote)
{
<img class="GuidanceNote" src='~/Content/Images/info.png' alt='Notes'
onmouseover="@Model.GuidanceNotesMouseover"
onmouseout="@Model.GuidanceNotesMouseOut" />
<span id="@Model.GuidanceNoteName" class='Info'>@Model.GuidanceNote</span>
}}
</div>
</td>
这里真正重要的一点是
@Html.TextBoxFor(m => m
那是因为在viewmodel中这是该属性的来源,我可以执行以下操作 -
[Required(AllowEmptyStrings = false, ErrorMessage = @"Must be completed")]
public RubikTextBox MatterNumber { get; set; }
因此,复杂类的行为类似于字符串,默认的隐式属性是由DataAnnotation验证的属性。
只是为了证明它,发出的HTML是(根据F12工具)
<input name="MatterNumber" id="MatterNumber" type="text" value="ZPH007-0864475"
data-val-required="Must be completed" data-val="true"
values="System.Collections.Generic.Dictionary`2+ValueCollection
[System.String,System.Object]"
keys="System.Collections.Generic.Dictionary`2+KeyCollection
[System.String,System.Object]" count="3">
目前我已经将它用于主要返回值的复杂类 复选框(可空) 货币(可以为空) DateTime(可空) 单选按钮列表 下拉列表(字符串) 短文本(文本框)和长文本(TextArea)。
我很高兴。