视图模型中的嵌套对象会混淆MVC 4路由?

时间:2014-10-28 11:45:34

标签: asp.net-mvc-4 razor model-binding

所以我有这个观点,它是由CMS生成的。视图的大脑位于RenderAction渲染的另一个视图中。

到目前为止它看起来像这样:

Main.cshtml

<div>CMS content</div>
@{
    var myContent = new MainContentModel() {
        SomethingUsedFurtherDown = "Easier for CMS people to edit"
    }

    Html.RenderAction("_Main", "Foo", new { arg1 = "this", arg2 = "that", content = myContent });
}

MainContentModel.cs

namespace MyApp.Services.ViewModels.Foo
{
    public class MainContentModel
    { 
        public string SomethingUsedFurtherDown { get; set; }
    }
}

MainViewModel.cs

namespace MyApp.Services.ViewModels.Foo
{
    public class MainViewModel
    {
        public string Arg1 { set; set; }
        public string Arg2 { set; set; }

        public string Name { get; set; }
        public string Age { get; set; }
        public string Address { get; set; }

        public MainContentModel Content { get; set; }
    }
}

_Main.cshtml

@model MyApp.Services.ViewModels.Foo.MainViewModel

@Html.EditorFor(m => m.Name)
@Html.EditorFor(m => m.Age)
@Html.EditorFor(m => m.Address)

<!-- whatever - doesn't matter -->

FooController.cs

namespace My.App.Controllers
{
    using System;
    using System.Web.Mvc;

    public class FooController
    {
        public ActionResult Main(string arg1, string arg2, MainContentModel cm)
        {
            var vm = new MainViewModel() { Arg1 = arg1, Arg2 = arg2, Content = cm };
            return this.View("_Main", vm);
        }
    }
}

一切正常。那我为什么要困扰你呢?嗯,这显然不是真正的代码。控制器方法还有很多参数,而且它们都变得相当混乱。所以我想我会从外部视图传递视图模型。

Main.cshtml

<div>CMS content</div>
@{
    var myVM = new MainViewModel() {
        Arg1 = "this"
        , Arg2 = "that"
        , Content = new MainContentModel() {
            SomethingUsedFurtherDown = "Easier for CMS people to edit"
        }
    };

    Html.RenderAction("_Main", "Foo", new { vm = myVM });
}

...只有控制器方法的一个参数

FooController.cs

namespace My.App.Controllers
{
    using System;
    using System.Web.Mvc;

    public class FooController
    {
        public ActionResult Main(MainViewModel vm)
        {
            return this.View("_Main", vm);
        }
    }
}

这就是麻烦开始的地方。我收到这个错误:

The view '_Main' or its master was not found or no view engine supports the searched locations. The following locations were searched:
~/Views/Foo/_Main.aspx
~/Views/Foo/_Main.ascx
~/Views/Shared/_Main.aspx
~/Views/Shared/_Main.ascx
~/Views/Foo/_Main.cshtml
~/Views/Foo/_Main.vbhtml
~/Views/Shared/_Main.cshtml
~/Views/Shared/_Main.vbhtml
~/Views/CMS/_Main.cshtml
~/Views/CMS/Foo/_Main.cshtml

但是,如果我删除了内容模型的初始化,那么它将再次起作用。好吧,好吧,它不会工作工作。但是错误消失了,让我想出了将内容模型添加到参数列表并将其分配给控制器方法中的视图模型的明显解决方案。

Main.cshtml

<div>CMS content</div>
@{
    var myVM = new MainViewModel() {
        Arg1 = "this"
        , Arg2 = "that"
    };
    var myCm = new MainContentModel() {
            SomethingUsedFurtherDown = "Easier for CMS people to edit"
    };

    Html.RenderAction("_Main", "Foo", new { vm = myVM, cm = myCm });
}

FooController.cs

namespace My.App.Controllers
{
    using System;
    using System.Web.Mvc;

    public class FooController
    {
        public ActionResult Main(MainViewModel vm, MainContentModel cm)
        {
            vm.Content = cm;
            return this.View("_Main", vm);
        }
    }
}

除了真实视图模型中存在相当多的子对象并且我不想将这些对象分成参数之外,哪个是好的,它会破坏本应该是一个整理练习的目的。

问题

MVC4是否应该无缝地绑定子对象,这是一个错误?或者它是不是以这种方式工作,我唯一的选择是将它们分成如上所述的额外参数?

干杯, .PD。

1 个答案:

答案 0 :(得分:1)

以防万一其他人陷入这个陷阱。问题不在于模型绑定。 MVC 4很好地绑定嵌套对象。我错过了错误的微妙之处。这里的标准是以&#34; real&#34;作为前缀。使用下划线查看名称,但未找到。失败发生在这里:

return this.View("_Main");

我没有在我的帖子中包含的内容(因为我记得,那会修复它!)是在RenderAction看起来真实的情况下这样:

RenderAction("Main", "Foo", new { area = "SomeArea", ... });

我在重构中错过了这个区域。非常尴尬,但如果它阻止别人在墙上撞头,那么耻辱将是值得的: - )