Is it possible to create a common @helper method using Razor?

I am trying to write an assistant in Razor that looks like this:

@helper DoSomething<T, U>(Expression<Func<T, U>> expr) where T : class 

Unfortunately, the parser thinks that <T is the beginning of the HTML element, and I get a syntax error. Is it possible to create an assistant with Razor, which is a common method? If so, what is the syntax?

+80
generics asp.net-mvc asp.net-mvc-3 razor
Jan 21 '11 at 15:52
source share
4 answers

No, It is Immpossible. Instead, you could write a regular HTML helper.

 public static MvcHtmlString DoSomething<T, U>( this HtmlHelper htmlHelper, Expression<Func<T, U>> expr ) where T : class { ... } 

and then:

 @(Html.DoSomething<SomeModel, string>(x => x.SomeProperty)) 

or if you aim the model at the first general argument:

 public static MvcHtmlString DoSomething<TModel, TProperty>( this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expr ) where T : class { ... } 

which allows you to call it like this (assuming your view is strongly typed, but this is a safe assumption because all views must be strongly typed :-)):

 @Html.DoSomething(x => x.SomeProperty) 
+46
Jan 21 '11 at 16:01
source share

This can be implemented inside a helper file with the @functions syntax, but if you want razor-style readability to reference you, you will also need to call a regular helper to make the HTML fit and finish.

Note that the functions in the Helper file are static, so you still need to pass the HtmlHelper instance from the page if you intend to use its methods.

eg. Views \ MyView.cshtml:

 @MyHelper.DoSomething(Html, m=>m.Property1) @MyHelper.DoSomething(Html, m=>m.Property2) @MyHelper.DoSomething(Html, m=>m.Property3) 

App_Code \ MyHelper.cshtml:

 @using System.Web.Mvc; @using System.Web.Mvc.Html; @using System.Linq.Expressions; @functions { public static HelperResult DoSomething<TModel, TItem>(HtmlHelper<TModel> html, Expression<Func<TModel, TItem>> expr) { return TheThingToDo(html.LabelFor(expr), html.EditorFor(expr), html.ValidationMessageFor(expr)); } } @helper TheThingToDo(MvcHtmlString label, MvcHtmlString textbox, MvcHtmlString validationMessage) { <p> @label <br /> @textbox @validationMessage </p> } ... 
+117
Mar 12 '11 at 10:11
source share

In all cases, the TModel will be the same (the model is declared for presentation), and in my case the TValue will be the same, so I was able to declare the type of the Expression argument:

 @helper FormRow(Expression<Func<MyViewModel, MyClass>> expression) { <div class="form-group"> @(Html.LabelFor(expression, new { @class = "control-label col-sm-6 text-right" })) <div class="col-sm-6"> @Html.EnumDropDownListFor(expression, new { @class = "form-control" }) </div> @Html.ValidationMessageFor(expression) </div> } 

If your model fields are all string , you can replace MyClass with string .

It might be nice to define two or three helpers with the specified TValue , but if you have something else to create some ugly code, I really haven't found a good solution. I tried wrapping @helper from a function placed inside the @functions {} block, but I never had this to work this way.

+2
Feb 26 '15 at 20:07
source share

if your main problem is to get the value of the name attribute for binding using a lambda expression, like @Html.TextBoxFor(x => x.MyPoperty) , and if your component has very complex html tags and needs to be implemented on the razor’s helper, then why not just create the HtmlHelper<TModel> extension method to resolve the binding name:

 namespace System.Web.Mvc { public static class MyHelpers { public static string GetNameForBinding<TModel, TProperty> (this HtmlHelper<TModel> model, Expression<Func<TModel, TProperty>> property) { return ExpressionHelper.GetExpressionText(property); } } } 

Your razor assistant should be as usual:

 @helper MyComponent(string name) { <input name="@name" type="text"/> } 

then here you can use it

 @TheHelper.MyComponent(Html.GetNameForBinding(x => x.MyProperty)) 
0
Nov 15 '13 at 1:56
source share



All Articles