我的模型有这种强类型的视图表单。问题是我似乎无法正确获取ID。我的视图模型中有表单模型,所以我必须调用一些元素:
<%: Html.TextBoxFor(m => m.Business.Business2)%>
问题在于此代码:
viewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(partialFieldName)
如果我的partialFieldName是“Business2”,它应返回“Business_Business2”,但它只返回“Business2”。但是,如果我使用
<%: Html.EditorFor(x => x.Business) %>
它返回“Business_Business2”。我不能使用Html.EditorFor,因为我有css类放在我的表单元素上。没有正确的ID,我无法做很多客户端验证,所以这真的让我烦恼。有什么想法吗?
以下是我的代码:
模型
public class BusinessModel
{
public string Business1 { get; set; }
public string Business2 { get; set; }
}
public class AccountModel
{
public string Account1 { get; set; }
[MustMatch("Account1")]
public string Account2 { get; set; }
}
public class SampleWrappedModel
{
public BusinessModel Business { get; set; }
public AccountModel Account { get; set; }
}
验证
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public sealed class MustMatchAttribute : ValidationAttribute
{
private const string DefaultErrorMessage = "Must match {0}";
public MustMatchAttribute(string propertyToMatch)
: base(DefaultErrorMessage)
{
PropertyToMatch = propertyToMatch;
}
public string PropertyToMatch { get; private set; }
public override string FormatErrorMessage(string name)
{
return String.Format(CultureInfo.CurrentUICulture, ErrorMessageString, PropertyToMatch);
}
public override bool IsValid(object value)
{
throw new Exception("MustMatchAttribute requires the DataAnnotationsMustMatchValidator adapter to be registered");
}
}
//Adapter class
public class DataAnnotationsMustMatchValidator : DataAnnotationsModelValidator<MustMatchAttribute>
{
public DataAnnotationsMustMatchValidator(ModelMetadata metadata, ControllerContext context, MustMatchAttribute attribute)
: base(metadata, context, attribute)
{
}
public override System.Collections.Generic.IEnumerable<ModelValidationResult> Validate(object container)
{
var propertyToMatch = Metadata.ContainerType.GetProperty(Attribute.PropertyToMatch);
if (propertyToMatch != null)
{
var valueToMatch = propertyToMatch.GetValue(container, null);
var value = Metadata.Model;
bool valid = Equals(value, valueToMatch);
if (!valid)
{
yield return new ModelValidationResult { Message = ErrorMessage };
}
}
}
public override System.Collections.Generic.IEnumerable<ModelClientValidationRule> GetClientValidationRules()
{
string propertyIdToMatch = GetFullHtmlFieldId(Attribute.PropertyToMatch);
yield return new ModelClientMustMatchValidationRule(ErrorMessage, propertyIdToMatch);
}
private string GetFullHtmlFieldId(string partialFieldName)
{
ViewContext viewContext = (ViewContext)ControllerContext;
return viewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(partialFieldName);
}
}
public class ModelClientMustMatchValidationRule : ModelClientValidationRule
{
public ModelClientMustMatchValidationRule(string errorMessage, string propertyIdToMatch)
{
ErrorMessage = errorMessage;
ValidationType = "mustMatch";
ValidationParameters.Add("propertyIdToMatch", propertyIdToMatch);
}
}
答案 0 :(得分:0)
TemplateInfo对GetFullHtmlFieldName和GetFullHtmlFieldId方法的作用是将HtmlFieldPrefix添加到传递的partialFieldName之前。如果我理解正确,你需要一种能够从labmda表达式返回html字段名称的帮助器
public static string GetHtmlFieldName<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
{
return ExpressionHelper.GetExpressionText(expression);
}
然后你可以使用
Html.GetHtmlFieldName(m => m.Business.Business2)
这将返回Business.Business2
答案 1 :(得分:0)
我不能使用Html.EditorFor,因为我有css类放在我的表单元素上。
然后您可以编写自定义编辑器模板。所以在你看来:
<%: Html.EditorFor(x => x.Business) %>
然后在~/Views/Shared/EditorTemplates/BusinessModel.ascx
内:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<BusinessModel>" %>
<%: Html.TextBoxFor(m => m.Business1) %>
<%: Html.TextBoxFor(m => m.Business2) %>
...
或者如果您不喜欢模板的传统地点和名称,您也可以自定义它:
<%: Html.EditorFor(x => x.Business, "MyBusinessTemplate") %>
或者如果只是在输入元素中应用其他属性,则可以更优雅的方式执行:writing a custom DataAnnotationsModelMetadataProvider。
我建议您始终使用EditorFor
代替TextBoxFor
。