asp.net mvc - net - ¿Es posible crear un método @helper genérico con Razor?
render partial asp net core (4)
En todos los casos, el TModel
será el mismo (el modelo declarado para la vista), y en mi caso, TValue
sería el mismo, así que pude declarar el tipo de argumento Expresión:
@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>
}
Si los campos de su modelo son todos de string
, puede reemplazar MyClass
con una string
.
Puede que no sea malo definir dos o tres ayudantes con TValue
definido, pero si tienes más que generen algún código feo, realmente no encontré una buena solución. Traté de envolver el @helper
desde una función que puse dentro del bloque @functions {}
, pero nunca conseguí que funcionara en esa ruta.
Estoy tratando de escribir un ayudante en Razor que se parece a lo siguiente:
@helper DoSomething<T, U>(Expression<Func<T, U>> expr) where T : class
Lamentablemente, el analizador piensa que <T
es el comienzo de un elemento HTML y termino con un error de sintaxis. ¿Es posible crear un ayudante con Razor que sea un método genérico? Si es así, ¿cuál es la sintaxis?
Esto es posible de lograr dentro de un archivo auxiliar con la sintaxis @functions
pero si quieres la legibilidad al estilo de la maquinilla de afeitar a la que te refieres, también necesitarás llamar a un helper habitual para que haga el ajuste HTML y finalice.
Tenga en cuenta que las funciones en un archivo Helper son estáticas por lo que aún tendría que pasar la instancia de HtmlHelper desde la página si tenía la intención de utilizar sus métodos.
por ejemplo, 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>
}
...
No, esto no es posible En su lugar, podría escribir una ayuda HTML normal.
public static MvcHtmlString DoSomething<T, U>(
this HtmlHelper htmlHelper,
Expression<Func<T, U>> expr
) where T : class
{
...
}
y entonces:
@(Html.DoSomething<SomeModel, string>(x => x.SomeProperty))
o si está apuntando al modelo como primer argumento genérico:
public static MvcHtmlString DoSomething<TModel, TProperty>(
this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TProperty>> expr
) where T : class
{
...
}
lo que le permitirá invocarlo de esta manera (suponiendo, por supuesto, que su vista esté fuertemente tipada, pero esa es una suposición segura, ya que todas las vistas deberían estar fuertemente tipadas de todos modos :-)):
@Html.DoSomething(x => x.SomeProperty)
si su problema principal es obtener el valor de atributo de nombre para el enlace utilizando la expresión lambda parece @Html.TextBoxFor(x => x.MyPoperty)
, y si su componente tiene etiquetas html muy complejas y debe implementarse en el asistente de afeitar, entonces ¿por qué? no solo cree un método de extensión de HtmlHelper<TModel>
para resolver el nombre de enlace:
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);
}
}
}
tu ayuda de afeitar debería ser como de costumbre:
@helper MyComponent(string name)
{
<input name="@name" type="text"/>
}
entonces aquí puedes usarlo
@TheHelper.MyComponent(Html.GetNameForBinding(x => x.MyProperty))