私は/編集を追加/ Entity Frameworkのオブジェクトのための機能を削除/基本的な検索を提供することを目的とMVCのセットを書いています。また、属性を使用して他のテーブルからドロップダウンをサポートするような、派手なこともいくつか行います。
プレイが主な目的はAdminField<T>
のアレイ、T
でフィールド/プロパティを表すの各要素を含む継承汎用コントローラ(T
がEFオブジェクトであるAdminController<T>
)です。 AdminController<T>
はAdminViewModel<T>
オブジェクトを生成できます。以下は、これらのオブジェクト間の関係のVisioチャートです。
問題
私の問題はビューです。値を表示するには、Html.EditorFor
/HiddenFor
/TextboxFor
ヘルパーを使用しています。高度に単純化されたビューは、フィールドをループしてその値を表示し、編集可能なフィールドであれば編集を許可します。
@model AdminViewModel<ExampleEFObject>
@using (Html.BeginForm())
{
foreach (var f in Model.Fields)
{
var expression = Model.ExpressionFromField(f);
<label class="control-label col-md-3">@f.DisplayName</label>
@if (!f.Editable)
{
@Html.TextBoxFor(expression, new { @class = "form-control", @disabled = "disabled" })
}
else
{
@Html.EditorFor(expression, new { htmlAttributes = new { @class = "form-control" } })
}
}
<input type="submit" value="Save" class="btn btn-primary" />
}
は、まあ、それは私がそれが見えるようにしたいものです:これは次のようになります。参照型であるフィールド/プロパティでうまく動作します。値型では、しかし、私はEditorFor
ライン上System.InvalidOperationException
エラーを取得する:「テンプレートが唯一のフィールドへのアクセス、プロパティへのアクセス、単一次元配列のインデックス、または単一のパラメータのカスタムインデクサ式で使用することができます」
をこれは、ViewModel内のT
のインスタンスにアクセスする式を返すExpressionFromField
メソッドの戻り値の型がExpression<Func<AdminViewModel<T>, object>>
であるためです。オブジェクト型を返すので、式を生成するときにボクシングが強制されるので、(例えば)t => t.Count
の代わりに、私のメソッドは実際にはt => Convert(t.Count)
を返します。
現在の回避策
私の現在の回避策は、Expression<Func<AdminViewModel<T>, int>> IntExpressionFromField(AdminField<T> field)
として定義される第2の方法を持つことです。 int
を返しますので、式でボクシングを強制しません。しかし、それは私の意見は非常に醜います:
@model AdminViewModel<ExampleEFObject>
@using (Html.BeginForm())
{
foreach (var f in Model.Fields)
{
var expression = Model.ExpressionFromField(f);
var intExpression = Model.IntExpressionFromField(f);
<label class="control-label col-md-3">@f.DisplayName</label>
@if (!f.Editable)
{
if (intExpression == null)
{
@Html.TextBoxFor(expression, new { @class = "form-control", @disabled = "disabled" })
}
else
{
@Html.TextBoxFor(intExpression, new { @class = "form-control", @disabled = "disabled" })
}
}
else
{
if (intExpression == null)
{
@Html.EditorFor(expression, new { htmlAttributes = new { @class = "form-control" } })
}
else
{
@Html.EditorFor(intExpression, new { htmlAttributes = new { @class = "form-control" } })
}
}
}
<input type="submit" value="Save" class="btn btn-primary" />
}
さらに悪いことに、これが唯一の1つの値の種類(int
)をサポートしています。また、小数点、長整数型、その他のものをサポートしたいと思います。それぞれのカスタムメソッドを作成しなくても、他のタイプに対して保護するためのすべてのロジックを作成する必要はありません。
ヘルプ!
この問題を解決するには、エレガントで簡単な方法が必要です。存在しない場合、次のステップはHtml
ヘルパーメソッドの使用を中止することだと思います。しかし、これはアプリケーションの他の部分と一貫性を失わせる必要があり、私はそれが問題を解決するだろうということを知らない。
ご協力いただければ幸いです。
EFオブジェクトをViewに渡すのは悪い習慣です。おそらく、(DatePickerViewModel、TextBoxViewModelなどのエディタテンプレートを使用する)いくつかの抽象的なFieldViewModelの実装を含む抽象FormViewModelを作成し、コントローラでそのViewModelを変換してEntity Frameworkエンティティの操作を更新する必要があります。あなたがサービス層を持っているならDTOに。 –
複雑なレイアウトや上手なユーザーインタラクションを行うことができないため、全体的に価値がないかもしれないので、多くのエンティティがない場合は、ViewModelsや手動コードに切り替えてエンティティを更新することが可能です。 –
@raderick:ありがとう応答する。私はEFオブジェクトをビューに渡さず、一般的なViewModelのみを渡しました。しかし、それが悪い習慣であるなら、なぜ私が将来的により良いアプローチを選ぶことができるのか理解したい。 私がこれをやっているのは、何種類かの基本的なメンテナンス機能しか必要としないオブジェクトタイプが数多くあるからです。私は何十もの同じMVCセットを持つことを避けたい。 あなたが言ったアプローチは信じられないほど重く、制限しているようですが、私はフォールバックオプションとしてそれを覚えています。 – Daniel