【问题标题】:How can I use a property named 'Model' in my viewmodel class?如何在我的视图模型类中使用名为“模型”的属性?
【发布时间】:2011-02-21 15:23:42
【问题描述】:

我有一个非常简单的视图模型类和一个强类型视图(它使用这个类作为视图模型)。

public class MatchModelRequest
{
    public string Country { get; set; }
    public string Make { get; set; }
    public string Model { get; set; }
    public DateTime RegDate { get; set; }
    public int EnginePower { get; set; }
    public string FuelType { get; set; }
    public string BodyType { get; set; }
    public string Transmission { get; set; }
    public int Cc { get; set; }
    public int Doors { get; set; }
}

问题是那里有一个名为“Model”的属性。

当我在视图中这样做时:

<%= Html.EditorFor(m => m) %>

我得到了一个包含MatchModelRequest 的所有属性的漂亮表格。完全没有问题(模型绑定也没有,在MatchModelRequest 对象中检索值时)。

但是当我在视图上像这样将它们拆分为单个字段时:

<div class="editor-field">
    <%= Html.TextBoxFor(m => m.Model)%>
    <%= Html.ValidationMessageFor(m => m.Model)%>
</div>

在上面使用 m.Model 的第一行上,我收到了一个未处理的异常 System.ArgumentException: Value cannot be null or empty

我想这与ViewPage 上的Model 属性有关,但除了给该属性取另一个名字之外,我看不出我能做些什么来解决这个问题。

在我的情况下,现在可以为该属性指定另一个名称,但我想将其命名为“模型”。而且并不总是可以更改模型的属性。

编辑

我一直在进一步调查这个问题,显然出错的部分位于 GetExpressionText(LambdaExpression expression) 方法中的 System.Web.Mvc.ExpressionHelper 中。有以下几行:

// If it starts with "model", then strip that away
if (nameParts.Count > 0 && String.Equals(nameParts.Peek(), ".model", StringComparison.OrdinalIgnoreCase)) {
    nameParts.Pop();
}

这就是实际的“模型”部分被剥离的地方......所以我想这是设计使然,然后我没有其他选择来重命名我的属性?

仍然欢迎提出建议。

顺便说一句,这是 MVC 2。有人可以检查这段代码是否仍然存在于 MVC 3 中吗?

【问题讨论】:

    标签: asp.net-mvc viewmodel


    【解决方案1】:

    是的,没错。我查看了 MVC 3 RTM 源代码,有两个地方从表达式中删除了“模型”。第一个是当我们使用像@Html.TextBoxFor("model")这样的字符串表达式时。

        public static string GetExpressionText(string expression) {
            return
                String.Equals(expression, "model", StringComparison.OrdinalIgnoreCase)
                    ? String.Empty    // If it's exactly "model", then give them an empty string, to replicate the lambda behavior
                    : expression;
        }
    

    如你之前所说,另一个在GetExpressionText(LambdaExpression expression)

        // If it starts with "model", then strip that away
        if (nameParts.Count > 0 && String.Equals(nameParts.Peek(), ".model", StringComparison.OrdinalIgnoreCase)) {
            nameParts.Pop();
        }
    

    所以,我认为现在最好的解决方案是重命名您的财产:)

    更新:实际上,它适用于 Mvc3,我只是测试了它。代码中有一个修复,请参见:

    else if (part.NodeType == ExpressionType.Parameter) {
        // Dev10 Bug #907611
        // When the expression is parameter based (m => m.Something...), we'll push an empty
        // string onto the stack and stop evaluating. The extra empty string makes sure that
        // we don't accidentally cut off too much of m => m.Model.
        nameParts.Push(String.Empty);
        part = null;
    }
    else {
        break;
    }
    

    【讨论】:

    • 感谢您的查找!我觉得奇怪的是这样的行为没有得到更好的记录......我的意思是,我不能成为第一个遇到这个问题的人,或者使用“模型”作为属性名,这是没有人做过的? ;-)
    • 非常好!但由于我们目前停留在 Visual Studio 2008 上,我认为我将不得不解决更改属性名称的“修复”问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-09
    • 2017-07-10
    • 2018-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-28
    相关资源
    最近更新 更多