1

ページの 1 つにかなり複雑なモデルがあります。これは、いくつかのネストされたモデル オブジェクトで構成されています。子コレクションを持つ子オブジェクトを使用するセクションでは、次のEditorForようにヘルパーを使用します。

@Html.EditorFor(m => m.CAS.LERoles[i].LE, "TinyText")

、私は次のようなものになります:

<input id="CAS_LERoles_0__LE" class="tinyText" type="text" value="0" name="CAS.LERoles[0].LE" data-val-required="The Legal Entity field is required." data-val-number="The field Legal Entity must be a number." data-val="true">

... これは素晴らしい。ただし、次のように、列挙型を選択リストに変換する独自のヘルパーを作成しました。

public static HtmlString EnumSelectListFor<TModel, TProperty>(
    this HtmlHelper<TModel> htmlHelper,
    Expression<Func<TModel, TProperty>> forExpression,
    object htmlAttributes,
    bool blankFirstLine)
    where TModel : class
    where TProperty : struct
{
    //MS, it its infinite wisdom, does not allow enums as a generic constraint, so we have to check here.
    if (!typeof(TProperty).IsEnum) throw new ArgumentException("This helper method requires the specified model property to be an enum type.");

    //initialize values
    var metaData = ModelMetadata.FromLambdaExpression(forExpression, htmlHelper.ViewData);
    var propertyName = metaData.PropertyName;
    var propertyValue = htmlHelper.ViewData.Eval(propertyName).ToStringOrEmpty();

    //build the select tag
    var returnText = string.Format("<select id=\"{0}\" name=\"{0}\"", HttpUtility.HtmlEncode(propertyName));
    if (htmlAttributes != null)
    {
        foreach (var kvp in htmlAttributes.GetType().GetProperties()
            .ToDictionary(p => p.Name, p => p.GetValue(htmlAttributes, null)))
        {
            returnText += string.Format(" {0}=\"{1}\"", HttpUtility.HtmlEncode(kvp.Key),
                HttpUtility.HtmlEncode(kvp.Value.ToStringOrEmpty()));
        }
    }
    returnText += ">\n";

    if (blankFirstLine)
    {
        returnText += "<option value=\"\"></option>";
    }

    //build the options tags
    foreach (var enumName in Enum.GetNames(typeof(TProperty)))
    {
        var idValue = ((int)Enum.Parse(typeof(TProperty), enumName, true)).ToString();
        var displayValue = enumName;

        // get the corresponding enum field using reflection
        var field = typeof(TProperty).GetField(enumName);
        var display = ((DisplayAttribute[])field.GetCustomAttributes(typeof(DisplayAttribute), false)).FirstOrDefault();
        var titleValue = string.Empty;
        if (display != null)
        {
            // The enum field is decorated with the DisplayAttribute =>
            // use its value
            displayValue = display.Name;
            titleValue = display.Description.ToStringOrEmpty();
        }

        returnText += string.Format("\t<option value=\"{0}\" title=\"{1}\"",
            HttpUtility.HtmlEncode(idValue), HttpUtility.HtmlEncode(titleValue));
        if (enumName == propertyValue)
        {
            returnText += " selected=\"selected\"";
        }
        returnText += string.Format(">{0}</option>\n", HttpUtility.HtmlEncode(displayValue));
    }

    //close the select tag
    returnText += "</select>\n";
    return new HtmlString(returnText);
}

そして、これを自分のページで次のように使用すると:

@Html.EnumSelectListFor(m => m.CAS.LERoles[i].APMasterRole)

私はこれで終わります:

<select name="APMasterRole" id="APMasterRole">
(stuff)
</select>

振り返ってみると、それは適切に翻訳されるだろうと思っていたと思いますが、今では自分が少しナイーブだったことに気づきました。適切な名前と ID を生成するために使用できるメカニズムが MVC フレームワークに組み込まれていることを本当に望んでいます。そうでなければ、これは反射の迷路のように見えます。

問題は、このような複雑なモデル オブジェクトの名前と ID の文字列を作成するメカニズムがあるかどうかです。もしそうなら、それはどのように使用されますか?そうでない場合、フォーム データをオブジェクト モデルにバインドできるように名前と ID を生成する比較的簡単な方法はありますか?

ありがとう!

4

1 に答える 1

3

適切な名前と ID を生成するために使用できるメカニズムが MVC フレームワークに組み込まれていることを本当に望んでいます。そうでなければ、これは反射の迷路のように見えます。

もちろん、そのような仕組みがあること。組み込みのヘルパーはどのようにそれを行うと思いますか? ASP.NET MVC フレームワークのソース コードを読んだことがありませんか? それともリフレクターか何かを使いますか?

string name = ExpressionHelper.GetExpressionText(forExpression);
var ti = htmlHelper.ViewContext.ViewData.TemplateInfo;
string fullHtmlFieldName = ti.GetFullHtmlFieldName(name);
string id = ti.GetFullHtmlFieldId(fullHtmlFieldName);
// Now go ahead and use fullHtmlFieldName and id

var returnText = string.Format(
    "<select id=\"{0}\" name=\"{1}\"", 
    id, 
    fullHtmlFieldName
);

ああ、忘れる前に:何も適切にエンコードしないこの恐ろしい文字列連結の代わりに、a を使用しTagBuilderて DOM 要素を生成してください。 ループ内の文字列の演算子は<select>言うまでもありません。+=文字列は不変であり、これによりメモリ割り当てが必要になります! 少なくともStringBuilder.

于 2012-07-02T16:40:01.243 に答える