2011-09-05 39 views
2

我有我的模型的強類型視圖窗體。問題是我似乎無法獲得正確的ID。我的觀點模型中它的形式模型,所以我要呼籲像一些要素:ASP.NET MVC2無法獲取元素的完整ID

<%: Html.TextBoxFor(m => m.Business.Business2)%> 

問題是與此代碼:

viewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(partialFieldName) 

如果我partialFieldName是「業務2」,它應該返回「Business_Business2」但它只返回「Business2」。但是,如果我使用

<%: Html.EditorFor(x => x.Business) %> 

它返回「Business_Business2」。我無法使用Html.EditorFor,因爲我有css類放置在我的表單元素上。如果沒有正確的身份證,我不能做很多客戶端驗證,所以這實際上是在擾亂我。有任何想法嗎?

這裏是我的代碼:

模式

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

@Timbo:是的。 – iamnobody

回答

0

的TemplateInfo做什麼用GetFullHtmlFieldName和GetFullHtmlFieldId方法,簡直就是前面加上HtmlFieldPrefix來傳遞partialFieldName 。如果我理解正確的話,你需要那種幫手能夠從labmda表達

public static string GetHtmlFieldName<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression) 
{ 
    return ExpressionHelper.GetExpressionText(expression); 
} 

返回HTML字段名,然後你可以使用

Html.GetHtmlFieldName(m => m.Business.Business2) 

這將返回Business.Business2

+0

謝謝你的回覆。我認爲這將工作,但我需要將完整的字段名稱/ ID從服務器傳遞給客戶端,所以只需在我的視圖中使用Html.GetHtmlFieldName將不適用於我。我嘗試通過TemplateInfo.HtmlFieldPrefix獲取HtmlFieldPrefix,但它只是返回一個空字符串。任何想法? – iamnobody

+0

你需要通過JavaScript或CSS #id選擇器? – archil

+0

是的。它是客戶端模型驗證,所以我需要從DataAnnotations將它傳遞給ModelClientValidationFule在客戶端的JavaScript。 – iamnobody

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