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.