ASP.NET MVC 3 gets name and editor name in JS

I am wondering if it is possible to get the HTML attribute "ID" of the generated element, the ASP.NET Web Forms Field.ClientID link.

So, I'm trying to do authentication in JavaScript. I am currently working on a Form Validator, so I have

RAZOR Template

@Html.TextEditorFor(m => m.aspnet_Membership.Email); 

Then js to check

 $('#MyForm').validate({ rules : { //and this is the part where I need email ID //I can do this by manually typing aspnet_Membership_Email //but I'm asking is there a way to get it like @Html.GetElementID(m => m.aspnet_Membership.Email): { required: true, email: true } } }); 

There are many fields, so I need this to avoid user input errors like apsnet .....

Remember that JS is in the template. not in external js file. (I do not start :))

Please do not focus only on Validator, I added it as an example. If I add a future prefix for each field in the form to have a unique identifier on the page, then I would run into problems such as fixing my js if the Field IDs are fixed.

Thanks in advance.

+4
source share
4 answers

The IdFor helper can help you with this task:

 @html.IdFor(m => m.aspnet_Membership.Email) 
+2
source

I would write my own extension method:

 public static class Helper { public static MvcHtmlString GetElementID<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression) { return MvcHtmlString.Create(GetPropertyName(expression)); } private static string GetPropertyName(Expression lambdaExpression) { IList<string> list = new List<string>(); var e = lambdaExpression; while (true) { switch (e.NodeType) { case ExpressionType.Lambda: e = ((LambdaExpression)e).Body; break; case ExpressionType.MemberAccess: var propertyInfo = ((MemberExpression)e).Member as PropertyInfo; var prop = propertyInfo != null ? propertyInfo.Name : null; list.Add(prop); var memberExpression = (MemberExpression)e; if (memberExpression.Expression.NodeType != ExpressionType.Parameter) { var parameter = GetParameterExpression(memberExpression.Expression); if (parameter != null) { e = Expression.Lambda(memberExpression.Expression, parameter); break; } } return string.Join("_", list.Reverse()); default: return null; } } } private static ParameterExpression GetParameterExpression(Expression expression) { while (expression.NodeType == ExpressionType.MemberAccess) { expression = ((MemberExpression)expression).Expression; } return expression.NodeType == ExpressionType.Parameter ? (ParameterExpression)expression : null; } } 

and usage that leads to aspnet_Membership_Email :

 @Html.GetElementID(m => m.aspnet_Membership.Email); 

This gives you a chain of concatenated properties based on a lambda expression. Basically, this is similar to the implementation of @Html.IdFor in MVC4 (however, I do not check their implementation).

+1
source

I think you are right to encapsulate the logic of generating IDs, although this is relatively simple. Your idea of ​​an HTML helper seems to be an effective way to do this (unlike, for example, exposing a bunch of identification values ​​along with the field values ​​in the model).

However, I'm curious why you don't use the unobtrusive authentication features and let it generate your validators for you?

If you add the [Required] attribute to the email property and enable the unobtrusive validator javascripts on the page where you will be drinking pin collages.

In your model:

 [Required] [Display(Name = "First Name")] [RegularExpression("([\r-~])*", ErrorMessageResourceType = typeof (AccountMessages), ErrorMessageResourceName = "FormFieldInvalid")] [StringLength(50)] public string FirstName { get; set; } 

In your markup:

 @Html.LabelFor(model => model.User.FirstName) @Html.TextBoxFor(model => model.User.FirstName) @Html.ValidationMessageFor(model => model.User.FirstName, null, new { @class = "errorMessageField" }) 
0
source

The class that uses the framework to create names (not identifiers for each) is a static class called ExpressionHelper and is publicly available in MVC3. It has one function called GetExpressionText that accepts lambda. In doing so, you will need to create your own IdFor shell to get the syntax you want from it.

This is the class that exists in MVC4:

 public static class NameExtensions { public static MvcHtmlString Id(this HtmlHelper html, string name) { return MvcHtmlString.Create(html.AttributeEncode(html.ViewData.TemplateInfo.GetFullHtmlFieldId(name))); } [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")] [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "Users cannot use anonymous methods with the LambdaExpression type")] public static MvcHtmlString IdFor<TModel, TProperty>(this HtmlHelper<TModel> html, Expression<Func<TModel, TProperty>> expression) { return Id(html, ExpressionHelper.GetExpressionText(expression)); } public static MvcHtmlString IdForModel(this HtmlHelper html) { return Id(html, String.Empty); } [SuppressMessage("Microsoft.Naming", "CA1719:ParameterNamesShouldNotMatchMemberNames", MessageId = "1#", Justification = "This is a shipped API.")] public static MvcHtmlString Name(this HtmlHelper html, string name) { return MvcHtmlString.Create(html.AttributeEncode(html.ViewData.TemplateInfo.GetFullHtmlFieldName(name))); } [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")] [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "Users cannot use anonymous methods with the LambdaExpression type")] public static MvcHtmlString NameFor<TModel, TProperty>(this HtmlHelper<TModel> html, Expression<Func<TModel, TProperty>> expression) { return Name(html, ExpressionHelper.GetExpressionText(expression)); } public static MvcHtmlString NameForModel(this HtmlHelper html) { return Name(html, String.Empty); } } 
0
source

All Articles