2012-08-14 336 views
3

我看到了一些類似的問題,但他們似乎是對於MVC的舊版本,我沒有運氣如何將它們應用於MVC3 。MVC3 C#自定義HtmlHelper輸入與驗證,客戶端和服務器端

基本上我已經寫了一個很好的小htmlhelper,它將顯示當前模型的選定參數,很像@Html.DisplayFor(),除了我的旁邊有一個編輯按鈕(原諒這些示例中缺少樣式! ):

button example

當這個按鈕被點擊它會做其中顯示編輯字段和頁面的其餘部分使用一些簡單的jQuery變灰了一下那些「彈出窗口」之一:

popup example

這是我的幫助:

public static HtmlString PopUpEditorFor<TModel, TProperty>(this HtmlHelper<TModel> html, Expression<Func<TModel, TProperty>> expression, bool textarea = false) 
    { 
     string id = html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(ExpressionHelper.GetExpressionText(expression)); 

     ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData); 

     var Display = new TagBuilder("span"); 
     Display.MergeAttribute("class", "Display"); 
     Display.InnerHtml = metadata.Model.ToString(); 

     var Edit_Button = new TagBuilder("span"); 
     Edit_Button.MergeAttribute("class", "Edit_Button"); 
     Edit_Button.InnerHtml = " Edit";// change to use resources file 

     var Display_Container = new TagBuilder("div"); 
     Display_Container.MergeAttribute("class", "Display"); 
     Display_Container.InnerHtml = Display.ToString(TagRenderMode.Normal) + Edit_Button.ToString(TagRenderMode.Normal); 

     var legend = new TagBuilder("legend"); 
     legend.InnerHtml = "Edit " + metadata.DisplayName ?? metadata.PropertyName; 

     var Editor_Box_Input = new TagBuilder("input"); 
     Editor_Box_Input.MergeAttribute("class", "Editor_Box"); 
     Editor_Box_Input.MergeAttribute("id", id); 
     Editor_Box_Input.MergeAttribute("name", id); 
     Editor_Box_Input.MergeAttribute("type", "text"); 
     Editor_Box_Input.MergeAttribute("value", metadata.Model.ToString()); 

     var Editor_Box_Textarea = new TagBuilder("textarea"); 
     Editor_Box_Input.MergeAttribute("class", "Editor_Box"); 
     Editor_Box_Input.MergeAttribute("id", id); 
     Editor_Box_Input.MergeAttribute("name", id); 
     Editor_Box_Input.MergeAttribute("type", "text"); 
     Editor_Box_Textarea.InnerHtml = metadata.Model.ToString(); 

     var Buttons = new TagBuilder("div"); 
     Buttons.MergeAttribute("class", "Buttons"); 
     Buttons.InnerHtml = QuestJSButton(html, "Cancel", "Option Cancel").ToString() + QuestJSButton(html, "Save", "Submit Save").ToString(); 

     var fieldset = new TagBuilder("fieldset"); 
     fieldset.InnerHtml += legend.ToString(TagRenderMode.Normal); 
     fieldset.InnerHtml += !textarea 
      ? Editor_Box_Input.ToString(TagRenderMode.SelfClosing) 
      : Editor_Box_Textarea.ToString(TagRenderMode.Normal); 
     fieldset.InnerHtml += Buttons.ToString(TagRenderMode.Normal); 

     var form_styled = new TagBuilder("div"); 
     form_styled.MergeAttribute("class", "Editor form_styled"); 
     form_styled.InnerHtml = fieldset.ToString(TagRenderMode.Normal); 

     var Editor_BG = new TagBuilder("div"); 
     Editor_BG.MergeAttribute("class", "Editor_BG"); 
     Editor_BG.InnerHtml = form_styled.ToString(TagRenderMode.Normal); 

     var PopUp_Editor = new TagBuilder("div"); 
     PopUp_Editor.MergeAttribute("class", "PopUp_Editor"); 
     PopUp_Editor.MergeAttribute("id", id); 
     PopUp_Editor.InnerHtml = Editor_BG.ToString(TagRenderMode.Normal) + Display_Container.ToString(TagRenderMode.Normal); 

     return PopUp_Editor.ToString(TagRenderMode.Normal).ToHtmlString(); 
    } 

其就被稱爲像一個正常的幫手:

@Html.PopUpEditorFor(model => model.property) 

,併產生下面的HTML:

 <div class="PopUp_Editor" id="property_id"> 
      <div class="Display"> 
      <span class="Display">property_value</span> 
      <span class="Edit_Button">Edit</span> 
      </div> 
      <div class="Editor_BG"> 
      <div class="Editor form_styled"> 
       <fieldset> 
       <legend>Edit Salutation</legend> 
       <input class="Editor_Box" id="property_id" name="property_id" type="text" value="property_value" /> 
       <div class="Buttons"> 
        <span class="Option Cancel">Cancel</span> 
        <span class="Submit Save">Save</span> 
       </div> 
       </fieldset> 
      </div> 
      </div> 
     </div> 

這個工作得很好,除了我想讓MVC3的真棒客戶機/服務器端驗證工作,我不知道如何去做這件事。我的目標是在顯示和輸入下方都顯示任何驗證錯誤消息,並且輸入可以獲得所需的類,以便在出現如下驗證錯誤時驗證其他任何htmlhelper輸入:

validation example

UPDATE

我敢肯定,我需要做的是讓我的助手包括必要的HTML屬性和span元素,這裏是當你添加一個視圖與「自動生成HTML編輯「模板:

<div class="editor-field"> 
<input class="text-box single-line" data-val="true" data-val-email="This is not a valid e-mail address." data-val-required="You must provide an e-mail address." id="Email_Address" name="Email_Address" type="text" value="[email protected]" /> 
</div> 
<div class="editor-validation"> 
<span class="field-validation-valid" data-valmsg-for="Email_Address" data-valmsg-replace="true"></span> 
</div> 

所以基本上我需要知道將這個應用到我的幫手的正確方法是什麼,並且如果可能使框架爲我完成大部分工作。

回答

1

正如您毫無疑問知道的,您需要獲得一些JavaScript(通常是jQuery)在客戶端上運行以獲得您所說的客戶端驗證的真棒。有時候這可以由框架生成,有時需要自己編寫。

你見過布拉德威爾遜的這個例子嗎? http://bradwilson.typepad.com/blog/2010/10/mvc3-unobtrusive-validation.html

下面是另一個例子是既完整,也比較短:http://www.falconwebtech.com/post/2012/04/21/MVC3-Custom-Client-Side-Validation-with-Unobtrusive-Ajax.aspx

編輯:如果你想使用標準的驗證,請確保您有這些腳本引用:

您需要這在你的網站。配置:

<appSettings> 
    <add key="ClientValidationEnabled" value="true"/> 
    <add key="UnobtrusiveJavaScriptEnabled" value="true"/> 
</appSettings> 

,這在你的頁面(或母版頁):

<script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script> 
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script> 
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script> 

最後,請記住,如果你是動態變化的東西(比如加載通過AJAX或任何東西),那麼你需要重新分析不引人注目的驗證這樣的:

$.validator.unobtrusive.parse($('formid')); 
+0

我很確定JavaScript已經存在,因爲它正在爲標準的HtmlHelpers工作,我想我只需要確保正確的html屬性應用於輸入字段並且正確的span元素已到位顯示消息,請參閱更新。 – Ben 2012-08-14 09:40:39

+0

另外我想我應該澄清驗證不需要自定義,因爲我只需要使用像required和maxlength這樣的內置函數。 – Ben 2012-08-14 09:48:33

+0

有點運氣,我所做的編輯會幫助你。 – 2012-08-14 11:48:01

5

上有,你可以在你的helper方法用它來獲得對模型的屬性驗證屬性的HtmlHelper的方法。

IDictionary<string, object> valAttributes = htmlHelper.GetUnobtrustiveValidationAttributes(propertyName, metaData); 

然後你就可以通過該集合環和合並的那些屬性,就像您已經在與別人做。