MVC3 C#Custom HtmlHelper用于输入验证,包括客户端和服务器端

时间:2012-08-14 08:37:01

标签: c# asp.net-mvc-3 validation html-helper

我已经看到了一些类似的问题,但它们似乎适用于较旧版本的MVC,我没有运气解决如何将它们应用于MVC3。

基本上我写了一个很好的小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

更新

我很确定我需要做的就是让我的助手包含必要的html属性和span元素,这里是使用“Edit”模板添加视图时自动生成的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="example@domain.com" />
</div>
<div class="editor-validation">
<span class="field-validation-valid" data-valmsg-for="Email_Address" data-valmsg-replace="true"></span>
</div>

所以基本上我需要知道将这个应用到我的助手的正确方法是什么,如果可能的话,让框架为我完成大部分工作。

2 个答案:

答案 0 :(得分:5)

HtmlHelper上有一个方法可以在helper方法中使用,以获取模型属性的验证属性。

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

然后你可以循环遍历该集合并合并这些属性,就像你已经在使用其他属性一样。

答案 1 :(得分:1)

正如您无疑知道的那样,您需要获取一些javascript(通常是jQuery)才能在客户端上运行,以获得您所说的真棒客户端验证。有时这可以由框架生成,有时您需要自己编写。

你有没有看过brad Wilson的这个例子? 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

编辑:如果您想使用标准验证,请确保引用了这些脚本:

你需要在web.config中使用它:

<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'));