【问题标题】:In ASP.NET MVC3, how should one render multiple PartialViews backed by multiple Models?在 ASP.NET MVC3 中,如何渲染由多个模型支持的多个 PartialView?
【发布时间】:2011-04-25 21:22:22
【问题描述】:

在 MVC3 Razor 中,如何创建一个包含多个表单的页面,让每个表单都是用自己的模型渲染的局部视图?

我们一直在尝试各种形式的调用 Html.RenderPartial(),传入部分视图名称以及我们通过 ViewBag 访问的模型实例,但我们尝试过的每种方法似乎都有严重的问题问题,因此我们必须对这在理想世界中应该如何运作有一个根本的误解。

我们发现了一些关于类似主题的 SO 回复 (like this one) 推荐了一个“超级模型”,其中包含对我们的局部视图可能需要使用的每个子模型的引用,但我们找不到您将如何使用的示例实际使用这些子模型的数据,例如尝试编写 EditorTemplates 时。

编辑:让我澄清一下我的问题。我们能够渲染局部视图甚至是动作(使用 Mark S. 推荐的 RenderAction)。但是,我们的主要问题是当这些表单提交回时,例如将模型的状态保存在该部分视图区域中,控制器似乎不知道我们引用的是什么模型。我们应该如何调用控制器?

我们尝试了几种不同的方式来呈现这些局部视图。我们的第一次尝试是这样的:

@using (Html.BeginForm("SaveAccountInfo", null, FormMethod.Post, new { id = "section1-form" }))
{
    @Html.EditorForModel("AccountInfo", (OurModels.AccountInfo) ViewBag.account_info)
}

ViewBag.account_info 包含这一局部视图的模型数据。

我们也尝试过:

@{Html.RenderPartial("FormAccountInfo", (OurModels.AccountInfo) ViewBag.account_info);}

现在:

@{Html.RenderAction("FormAccountInfo", "Main", new { account_info = (OurModels.AccountInfo) ViewBag.account_info }); }

但是无论我们使用哪种方法在页面上呈现这个表单,当该表单被提交进行处理时,我们似乎无法通过模型访问任何提交的数据?我觉得我们在做一些非常愚蠢的事情,但我们是 MVC 的新手。

【问题讨论】:

    标签: asp.net-mvc-3 razor models


    【解决方案1】:

    不要陷入抽象,从您呈现页面到调用控制器方法的时间,您只在 HTML 和 HTTP 中工作。

    如果您想以不同的方式回帖,有很多方法可以做到这一点。您的页面上可以有多个 HTML 表单,或者您可以使用 jQuery 之类的东西来执行发布。哪个控制器操作接收您的帖子以及发回哪些数据取决于 HTML 页面上的表单及其内容。 MVC 处理程序将获取请求,并尝试将请求 URL 和内容绑定到与其匹配的可用操作之一。

    要“回发模型”,您需要以模型绑定器可以读取的方式将数据发送回合适的操作。这可能是 JSON 数据(如果您使用的是 MVC 3)或具有名称-值对的表单。控制器虽然对请求数据的页面或其创建方式一无所知。它甚至不知道请求是否是由页面发出的。

    您可以通过制作一个普通的 HTML 页面来亲自尝试,该页面上带有一个设置为发布到您的 MVC 控制器之一的 URL 的表单。只要表单字段的名称与控制器动作参数的属性名称匹配,MVC 就会绑定它并调用动作。

    如果您有复杂的视图,您可能会发现 jQuery post 是一种不错的选择,它具有一些从页面收集数据并创建 JSON 对象以发回的客户端方法。使用该方法可以非常精确地控制发回的数据,而使用表单则有限制(例如重叠数据等)。

    编辑 - 回复评论

    这是一个使用原始 HTML 的示例,只是为了展示一个非常简单的案例:

    Public Class HomeController
    
        'Other action methods...
    
        <HttpPost()>
        Function SayHello(myName As String) As ActionResult
            Return Content("Hello " & myName)
        End Function
    
    End Class
    

    还有 HTML 表单(我在 Index 视图中添加了这个,但它绝对可以放在任何地方)

    <form action="/Home/SayHello" method="post">
        <input type="text" name="myName" />
        <input type="submit" />
    </form>
    

    我在&lt;input&gt; 上设置了名称以匹配参数名称,这为 MVC 提供了帮助。虽然只有 1 个值被发回,但我可以将其命名为别的。但是,如果我这样做:

    <form action="/Home/SayHello" method="post">
        <input type="text" name="aName" />
        <input type="text" name="anotherName" />
        <input type="submit" />
    </form>
    

    ...那么模型绑定器将不知道它应该使用哪个值,并且您会得到未正确设置的值。

    不过改成这样:

    <form action="/Home/SayHello" method="post">
        <input type="text" name="myName" />
        <input type="text" name="anotherName" />
        <input type="submit" />
    </form>
    

    ...并且模型绑定器现在能够使用名称来正确识别要使用的值和要忽略的值。

    在强类型操作的情况下:

    Public Class HomeController
    
        <HttpPost()>
        Function SayHello(person As SimplePerson) As ActionResult
            Return Content("Hello " & person.FirstName)
        End Function
    
    End Class
    
    Public Class SimplePerson
        Public Property FirstName As String
        Public Property Surname As String
    End Class
    

    您需要有与属性名称对应的表单名称。我的 aName/anotherName 表单会发回正确的形状,但模型绑定器不会设置任何属性,因为它不知道什么是什么。然而这会起作用:

    <form action="/Home/SayHello" method="post">
        <input type="text" name="FirstName" />
        <input type="text" name="Surname" />
        <input type="submit" />
    </form>
    

    【讨论】:

    • 非常感谢,这为 MVC 如何处理我以前不清楚的事情提供了一些启示。现在看来我们的问题可能出在其他地方,那么,由于我们看到调用的动作,只是传递到例程中的 Model 对象具有空/默认值,而 ModelState.IsValid 不应该是假的。 MVC 处理程序是否创建模型的实例,然后根据 HTTP 发布参数设置每个属性?在这方面失败的地方有什么调试建议吗?
    • 是的,差不多就是这样。有一些命名约定可以帮助模型绑定器,这就是 HTML 助手在处理这类事情时派上用场的地方。对于调试,您可以使用 Fiddler 之类的工具或浏览器的开发工具来检查您正在发出的请求,或从您的控制器中检查请求。
    • 感谢理查德的帮助。我们仍然遇到一个问题,我们正在回发,我们正在发送与我们的模型属性匹配的所有正确命名的表单值,并且绑定器正在将我们发送到正确的方法中,并传入我们的模型实例-- 但属性值都是默认值。我尝试在各种设置器上添加断点,但它们没有被击中。就像活页夹正在创建实例,但由于某种原因没有从 HTML 表单值中设置属性名称。一旦我有街头信誉,我会立即标记您的回复。
    • 其他可能有帮助的事情是,您可以从 CodePlex - aspnet.codeplex.com 下载 ASP.Net MVC 的完整源代码 - 然后参考源代码版本而不是引用随附的 DLL .这将允许您检查代码,在框架内设置断点,并准确查看发生了什么。我认为默认模型绑定器使用反射来设置属性值 - 所以你可能不会看到你的设置器被调用?您可能需要放入具有简单属性的 ViewModel 层,然后从中创建域对象。
    • 谢谢,我们会试试看!
    【解决方案2】:

    您可以使用Html.RenderAction() 方法。它提供了一系列功能,允许您进行渲染和操作,并让它调用从您的数据存储中获取自己的信息。这是文档的链接:http://msdn.microsoft.com/en-us/library/system.web.mvc.html.childactionextensions.renderaction.aspx。

    【讨论】:

    • 好的,谢谢。我们将其视为 RenderPartial 的替代方案,但希望有一些我们只是缺少的更直观的东西。我仍在尝试找出一个很好的资源来说明如何使用 RenderAction(或 RenderPartial 或类似方法)做类似的事情。谁啊,为什么不像渲染 PartialView 那样简单,每个 PartialView 都指定它的@model? :-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-09
    相关资源
    最近更新 更多