新视图或部分视图

4
这是情况:
我有一个ASP.NET MVC 4应用程序。当我运行应用程序时,转到一个页面,控制器上的Index动作接受一个Guid作为id参数。使用该id从数据库获取项目列表并将其放入ViewModel中。将此ViewModel传递给View,该View将所有项目列为ActionLink(如果需要可以更改)。当我点击其中一个项目时,我想根据所选链接的id获取其他项目的列表,并将此新列表显示在第一个列表旁边。
但这是我的问题(我已经卡了两天): 最佳方法是什么?转到新页面还是使用部分视图? 因为我既尝试了转到新页面也尝试了使用部分视图,显然我肯定做错了一些事情,因为似乎没有一种方法可行。我不需要任何AJAX之类的帮助程序,只需要正确的方法来完成这项工作... :)
提前感谢!
更新:我已经有的代码
视图:
@foreach (var order in Model.Orders)
{
    <p>@Html.ActionLink(order.Name,
                        "OrderItems",
                        "OrdersController",
                        new { id = order.Id },
                        null)
    </p>
}

@if (Model.Detail != null)
{
    @Html.Partial("_OrderItemsByOrder", Model)
}

Controller

public ActionResult Index(Guid id)
{
    var orders = Services.GetOrders(id);
    var viewModel = new OrdersViewModel { Orders = orders };
    return View(viewModel);
}

public ActionResult OrderItems(Guid id, OrdersViewModel model)
{
    var orderItems = Services.GetOrderLines(id);
    var viewModel = new OrdersViewModel
    {
        Orders = model.Orders,
        Detail = new OrderDetailViewModel { OrderItems = orderItems }
    };
    return PartialView(viewModel);
}

我有点困惑你到底想向用户返回什么。你是想返回一个订单列表,然后能够点击/选择它们并查看该订单的详细信息吗? - John
3个回答

3
你很可能(为了用户易用性)想要使用AJAX从AJAX响应中拉取“其他项目”的列表(JSON很可能,或者如果您真的想避免JavaScript,则为部分HTML页面)
如果您真的不想使用AJAX,可以先提取所有项目和所有“其他项目”并将它们存储在“隐藏”字段中,然后再进行两个选择框。

http://www.plus2net.com/javascript_tutorial/dropdown-list.php

例子: http://www.plus2net.com/javascript_tutorial/dropdown-list-demo.php

不过,除非人们经常使用每个下拉列表,或者选项数量非常有限,否则我会选择AJAX选项。

Ajax: http://www.plus2net.com/php_tutorial/ajax_drop_down_list.php

只想指出的是,不需要使用下拉框来选择/填充,您只需更改代码以填充div或任何要素即可 :)


很抱歉,您的回答并没有为我澄清问题。用户体验现在不是问题,我需要的是如何完成这个基本结构。 - Abbas
也许你可以发布一下你现在拥有的内容?你是否查看了示例并查看源代码以了解它们正在做什么? - John
@Abbas,你需要使用JavaScript来完成这个任务。你有两个选择:要么在初始页面加载时拉下所有的“其他选项”,要么在需要时使用AJAX动态地拉下它们。你不想每次有人选择第一个选项时都加载一个不同的页面,因为这样会更难以操作,并且用户体验也会变差。 - John
我编辑了我的帖子并添加了一些代码。好的,现在如果我使用AJAX,作为一个不是专家的人,我该如何做呢?我应该在同一个视图中呈现结果吗,还是...? - Abbas
在 AJAX 的情况下:一个视图显示你所拥有的内容,另一个视图仅呈现“其他项目”的列表。 - Onkelborg

2

有几种方法可以实现这样的主/细节页面,没有最好的方法。 AJAX可能是最优雅和用户友好的方法,但这并不是“正确”的答案。

从您发布的代码来看,您可以做的最简单的事情是拥有一个操作方法和一个视图。

public class OrdersViewModel
{
    public IEnumerable<Order> Orders { get; set; }
    public OrderItems SelectedOrderItems { get; set; }
}

public ActionResult Orders(Guid id, Guid? orderId)
{
    var model = new OrdersViewModel();
    model.Orders = Services.GetOrders(id);

    if (orderId != null)
    {
        model.SelectedOrderItems = Services.GetOrderLines(orderId);
    }

    return View(model);
}

这种基本的方法的缺点是,你的Url可能会有2个Guid,而且此示例并不验证orderId是否实际由(用户?)Id拥有,无论第一个Guid表示什么。不过,你可以用几行代码来处理这个问题。
更优雅的处理方法是,如果你不介意Url改变,那么可以使用第二个操作方法。我希望你能从订单详情本身或以某种方式确定订单详情的“所有者”,而不需要将其传递到操作方法中。这有助于确保你的视图只显示来自正确主人的详细信息。
public ActionResult OrderDetails(Guid id /*the id of the order*/)
{
    var orderLines = Services.GetOrderLines(id);

    var model = new OrdersViewModel();
    //ideally you could get to the "owner id" of the order from the order lines itself
    //depending on how your domain model is set up
    model.Orders = Services.GetOrders(orderLines.Order.OwnerId); 
    model.SelectedOrderItems = orderLines;

    return View("Orders", model); //render the same view as the Orders page if like
}

按照您提出的问题,您的视图大部分可以保持不变。渲染代表所有订单的操作链接。然后如果模型中有订单细节,则呈现订单细节:

@if (Model.SelectedOrderItems!= null)
{
    /* markup here or a render partial call */
}

如果您在其他页面上呈现订单详细信息,您需要将订单详细信息放入部分视图中,以避免重复标记。如果仅在此处呈现,则没有理由不能在此视图中直接编写标记。


1
我建议这样做:
  1. 您有一个带有操作的控制器。该操作需要两个参数,一个是您的guid,另一个是可选的其他id
  2. 您有一个“mainview”,列出您的项目
  3. 在您的控制器中,添加另一个操作,这次仅使用一个参数,即id
  4. 添加另一个视图,但这次是部分视图,显示其他项目

动作1将项目列表放入视图模型中,并提供可选的id以呈现其他项目。

动作3将一些其他项目的列表放入视图模型中

动作1呈现视图2,动作3呈现视图4。如果视图模型如此指示,则视图2呈现动作3。

基本上,当未选择特定项时,执行链将如下所示: 1 => 2 => 完成

但是当选择了项目时,链将如下所示: 1 => 2 => 3 => 4

(当然,这只是一种方法..)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接