7

最近、ASP.NET MVC 表示テンプレートで問題が発生しました。これが私のモデルだとしましょう:

public class Model
{
    public int ID { get; set; }
    public string Name { get; set; }
}

これはコントローラーです:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View(new Model());
    }
}

これが私の見解です:

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<DisplayTemplateWoes.Models.Model>" %>

<!DOCTYPE html>

<html>
<head runat="server">
    <title>Index</title>
</head>
<body>
    <div>
        <%: Html.DisplayForModel() %>
    </div>
</body>
</html>

何らかの理由ですべての文字列の表示テンプレートが必要な場合は、次のような String.ascx 部分ビューを作成します。

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<string>" %>

<%: Model %> (<%: Model.Length %>)

そして、ここに問題があります。実行時に次の例外がスロー されます。

Model クラスの整数プロパティと文字列プロパティの両方に String.ascx が使用されているようです。私はそれが文字列プロパティにのみ使用されることを期待していました - 結局、Object.ascx や Int32.ascx ではなく String.ascx という名前になっています。

これは設計によるものですか?はいの場合 - それはどこかに文書化されていますか? そうでない場合 - バグと見なすことができますか?

4

1 に答える 1

4

これは設計によるものと思われます。文字列テンプレートをより一般的にする必要があります。文字列テンプレートは、独自のテンプレートを持たないすべての非複雑なモデルの既定のテンプレートとして機能します。

文字列のデフォルト テンプレート (FormattedModelValue はオブジェクト):

internal static string StringTemplate(HtmlHelper html) {
    return html.Encode(html.ViewContext.ViewData.TemplateInfo.FormattedModelValue);
}

テンプレートの選択は次のようになります。

foreach (string templateHint in templateHints.Where(s => !String.IsNullOrEmpty(s))) {
    yield return templateHint;
}

// We don't want to search for Nullable<T>, we want to search for T (which should handle both T and Nullable<T>)
Type fieldType = Nullable.GetUnderlyingType(metadata.RealModelType) ?? metadata.RealModelType;

// TODO: Make better string names for generic types
yield return fieldType.Name;

if (!metadata.IsComplexType) {
    yield return "String";
}
else if (fieldType.IsInterface) {
    if (typeof(IEnumerable).IsAssignableFrom(fieldType)) {
        yield return "Collection";
    }

    yield return "Object";
}
else {
    bool isEnumerable = typeof(IEnumerable).IsAssignableFrom(fieldType);

    while (true) {
        fieldType = fieldType.BaseType;
        if (fieldType == null)
            break;

        if (isEnumerable && fieldType == typeof(Object)) {
            yield return "Collection";
        }

        yield return fieldType.Name;
    }
}

したがって、文字列のみのテンプレートを作成する場合は、次のようにする必要があります (String.ascx):

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<object>" %>

<% var model = Model as string; %>
<% if (model != null) { %>
    <%: model %> (<%: model.Length %>)
<% } else { %>
    <%: Model %>
<% } %>
于 2011-02-18T12:01:59.133 に答える