Razorで次のようなヘルパーを作成しようとしています。
@helper DoSomething<T, U>(Expression<Func<T, U>> expr) where T : class
残念ながら、パーサーは<T
はHTML要素の始まりであり、構文エラーになります。一般的な方法であるRazorでヘルパーを作成することはできますか?もしそうなら、構文は何ですか?
いいえ、これは不可能です。代わりに、通常のHTMLヘルパーを作成できます。
public static MvcHtmlString DoSomething<T, U>(
this HtmlHelper htmlHelper,
Expression<Func<T, U>> expr
) where T : class
{
...
}
その後:
@(Html.DoSomething<SomeModel, string>(x => x.SomeProperty))
または、最初の一般的な引数としてモデルをターゲットにしている場合:
public static MvcHtmlString DoSomething<TModel, TProperty>(
this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TProperty>> expr
) where T : class
{
...
}
このように呼び出すことができます(もちろん、ビューは強く型付けされていると仮定しますが、すべてのビューはとにかく強く型付けされるべきなので、これは安全な仮定です:-)):
@Html.DoSomething(x => x.SomeProperty)
このisは、@functions
構文ですが、参照しているカミソリスタイルの読みやすさを望む場合は、通常のヘルパーを呼び出してHTMLのフィットとフィニッシュを行う必要もあります。
ヘルパーファイルの関数は静的であるため、そのメソッドを使用する場合は、ページからHtmlHelperインスタンスを渡す必要があります。
例えば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>
}
...
すべての場合で、TModel
は同じ(ビューに対して宣言されたモデル)であり、私の場合、TValue
は同じになるので、Expressionを宣言することができました引数のタイプ:
@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>
}
モデルフィールドがすべてstring
の場合、MyClass
をstring
に置き換えることができます。
TValue
を定義して2つまたは3つのヘルパーを定義するのは悪くないかもしれませんが、それ以上いコードを生成するものがある場合、私は本当に良い解決策を見つけませんでした。 @helper
ブロック内に配置した関数から@functions {}
をラップしようとしましたが、そのパスで機能することはありませんでした。
主な問題がnameラムダ式を使用したバインディングの属性値の取得である場合、@Html.TextBoxFor(x => x.MyPoperty)
のように見え、コンポーネントが非常に複雑なhtmlタグを持ち、かみそりヘルパーに実装する必要がある場合、次に、HtmlHelper<TModel>
の拡張メソッドを作成してバインディング名を解決しないのはなぜですか。
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);
}
}
}
あなたのかみそりのヘルパーはいつものようになります:
@helper MyComponent(string name)
{
<input name="@name" type="text"/>
}
ここで使用できます
@TheHelper.MyComponent(Html.GetNameForBinding(x => x.MyProperty))