質問

my actual problem was here: Clinetside regular expression validation in MVC4

My model is:

public partial class PartyRole
{
[UIHint("TextBox")]
[RegularExpression(@"^.{5,}$", ErrorMessage="Minimum 5 characters required")]
[StringLength(50, ErrorMessage="Maximum {2} characters exceeded")]
public string Title { get; set; }
}

My uihint template (TextBox.cshtml)

@Html.TextBoxFor(m => Model, new {@class="txt"})

If I do not use UIHint, all the validation messages are rendered to client side. If I use UIHInt, not validation attributes for my regular expressions are generated on client side and validations are happening from server.

also, I have overriden the object.cshtml

@functions
{
bool ShouldShow (ModelMetadata metadata)
{
    return metadata.ShowForEdit
        && metadata.ModelType != typeof(System.Data.EntityState)
        && !metadata.IsComplexType
        && !ViewData.TemplateInfo.Visited(metadata);
}
}

@if (ViewData.TemplateInfo.TemplateDepth > 1)
{
if (Model == null)
{
    @ViewData.ModelMetadata.NullDisplayText
}
else
{
    @ViewData.ModelMetadata.SimpleDisplayText
}
}
else
{
ViewData.Clear();

foreach (var prop in ViewData.ModelMetadata.Properties.Where(pm => ShouldShow(pm)))
{
    if (prop.HideSurroundingHtml)
    {
        @Html.Editor(prop.PropertyName)
    }
    else if (prop.DisplayName == "Id")
    {
        <div></div>   
    }
    else if (!string.IsNullOrEmpty(Html.Label(prop.PropertyName).ToHtmlString()))
    {
        <div class="editor-label">@Html.Label(prop.PropertyName)</div>
    }
    <div class="editor-field">@Html.Editor(prop.PropertyName) @Html.ValidationMessage(prop.PropertyName, "")</div>
}
}

Not sure if this causing any issue.

can somebody advise what am I doing wrong here?

役に立ちましたか?

解決

Here's the thing. Unobtrusive client side validation uses HTML5 data-* attributes that are generated on your <input> fields. When you remove the UIHint, your custom template is no longer used and if you inspect the generated markup you will see that the <input> field has data-* attributes on it:

<input class="input-validation-error text-box single-line" data-val="true" data-val-length="Maximum 0 characters exceeded" data-val-length-max="50" data-val-regex="Minimum 5 characters required" data-val-regex-pattern="^.{5,}$" id="Title" name="Title" type="text" value="1" />

Now if you put your UIHint and look at the generated HTML you will see:

<input class="txt" id="Title" name="Title" type="text" value="some title" />

Alright, this explains why your code doesn't work.

Now you probably wanna know why there are no data-* attributes in your template? Because the HTML helpers such as Html.TextBoxFor generate those attributes only if they are placed inside a form. So you have to cheat and manually instantiate a FormContext to trick the helper into thinking that it is used inside a form. Actually there's an Html.BeginForm but this form is in your main view and inside the template the helper doesn't know that. Call it a bug or whatever but it's how things are.

So you could simply create a FormContext in your template:

@{
    this.ViewContext.FormContext = new FormContext();
}

@Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, new { @class="txt" })

and now your <input> field will have the necessary data-* attributes on it so that unobtrusive validation works as expected.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top