如何在viewmodel类中使用名为“Model”的属性?

时间:2011-02-21 15:23:42

标签: asp.net-mvc viewmodel

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

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

我认为这与Model上的ViewPage属性有关,但我不知道如何解决这个问题,而不仅仅是给该属性另一个名字。

在我的情况下,现在可以为该属性赋予另一个名称,但我希望将其命名为“Model”。而且并不总是可以改变模型的属性。

修改

我一直在进一步研究这个问题,显然出现问题的部分位于GetExpressionText(LambdaExpression表达式)方法的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中是否仍然存在此代码吗?

1 个答案:

答案 0 :(得分:3)

是的,那是对的。我查看了MVC 3 RTM源代码,有两个地方从表达式中删除了“Model”。首先是我们使用像@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;
}