如何解耦关系MVC数据

时间:2011-05-15 20:05:35

标签: asp.net-mvc asp.net-mvc-3 asp.net-mvc-routing

考虑这个场景:

我想为Northwind数据库构建一个MVC应用程序。我希望有一个列出一些订单的视图,我想创建CustomerID和EmployeeID的链接以及[OrderDetails]的详细信息链接,这样当用户点击任何这些链接时,相关数据将出现在同一页面中。

我的问题是如何将这些相互关联的数据解耦为在页面中显示相关数据的视图和控制器,以及负责信息各个部分的控制器。

另外,如何为此示例配置路由?

<table width="500px">
    <tr>
        <th></th>
        <th>
            OrderID
        </th>
        <th>
            CustomerID
        </th>
        <th>
            EmployeeID
        </th>
        <th>
            OrderDate
        </th>
        <th>
            RequiredDate
        </th>
        <th>
            ShippedDate
        </th>
        <th>
            ShipVia
        </th>            
        <th>
            OrderDetails
        </th>   
    </tr>

<% foreach (var item in Model) { %>

    <tr>
        <td>
            <%: Html.ActionLink("Edit", "Edit", new { id=item.OrderID }) %> |
            <%: Html.ActionLink("Details", "Details", new { id=item.OrderID })%> |
            <%: Html.ActionLink("Delete", "Delete", new { id=item.OrderID })%>
        </td>
        <td>
            <%: item.OrderID %>
        </td>
        <td>
            <%: item.CustomerID %>
        </td>
        <td>
            <%: item.EmployeeID %>
        </td>
        <td>
            <%: String.Format("{0:g}", item.OrderDate) %>
        </td>
        <td>
            <%: String.Format("{0:g}", item.RequiredDate) %>
        </td>
        <td>
            <%: String.Format("{0:g}", item.ShippedDate) %>
        </td>
        <td>
            <%: item.ShipVia %>
        </td>            
        <td>
            <%: Html.ActionLink("OrderDetails", "GetOrderDetails", new { id = item.OrderID })%>
        </td>
    </tr>

<% } %>

</table>

<p>
    <%: Html.ActionLink("Create New", "Create") %>
</p>

<div>
    <p>
        <% Html.RenderPartial("GetOrderDetails"); %>
    </p>
    <%--<uc1:GetOrderDetails ID="GetOrderDetails1" runat="server" />--%>
</div>

和订单明细部分视图:

<table>
    <tr>
        <th></th>
        <th>
            OrderID
        </th>
        <th>
            ProductID
        </th>
        <th>
            UnitPrice
        </th>
        <th>
            Quantity
        </th>
        <th>
            Discount
        </th>
    </tr>

<% foreach (var item in Model) { %>

    <tr>
        <td>
            <%: Html.ActionLink("Edit", "Edit", new { id=item.OrderID }) %> |
            <%: Html.ActionLink("Details", "Details", new { id=item.OrderID })%> |
            <%: Html.ActionLink("Delete", "Delete", new { id=item.OrderID })%>
        </td>
        <td>
            <%: item.OrderID %>
        </td>
        <td>
            <%: item.ProductID %>
        </td>
        <td>
            <%: String.Format("{0:F}", item.UnitPrice) %>
        </td>
        <td>
            <%: item.Quantity %>
        </td>
        <td>
            <%: item.Discount %>
        </td>
    </tr>

<% } %>

</table>

<p>
    <%: Html.ActionLink("Create New", "Create") %>
</p>

global.asax中:

public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");



        routes.MapRoute(
            "Default2", // Route name
            "{controller}/{action}/{OrderId}/{CustomerID}", // URL with parameters
            new { controller = "NorthwindOrders", action = "Index", OrderId = UrlParameter.Optional, CustomerID = UrlParameter.Optional } // Parameter defaults
        );

        routes.MapRoute(
            "Default", // Route name
            "{controller}/{action}/{id}", // URL with parameters
            new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
        );
    }

鉴于这种结构;单击任何OrderDetails链接时,如何在订单列表下显示订单详细信息?

而且,当我点击OrderDetails链接时,为什么URL显示如下:

http://localhost:49444/NorthwindOrders/GetOrderDetails?id=10250

我希望网址以这种方式显示:

http://localhost:49444/NorthwindOrders/GetOrderDetails/10250

3 个答案:

答案 0 :(得分:2)

尼马,
你可以通过局部视图或渲染动作来实现,json可以显示数据 基本的例子就是这里的例子: http://www.asp.net/mvc/tutorials/iteration-7-add-ajax-functionality-cs

或非常受欢迎的选项是jquery.dialog()

中任务的显示操作

取决于您想要继续的方式 CPO

<小时/> 订正:

我的坏。 从逻辑的角度来看,就是这样:
这取决于你,你想要走哪条路。 (从我的角度来看)

分离逻辑的好处是:

  1. 简单易懂,因为控制器仅与例如:orders
  2. 的操作相关
  3. 如果需要,可以在更多地方使用
  4. 只能测试小件物品,例如只有一个测试箱/夹具到控制器只有订单
  5. 适用于更复杂的项目
  6. 另一方面

    1. 将所有内容保存在一个控制器中并按区域分割逻辑
    2. Eveything在一起,很容易看到其他方法和他们做什么
    3. 希望这就是你要找的东西 CPO

答案 1 :(得分:2)

对于您的路由问题:

如果你设置了这样的路线:

    routes.MapRoute(
        "orderdetails", // Route name
        "{controller}/{action}/{id}", // URL with parameters
        new { controller = "NorthwindOrders", action = "GetOrderDetails", id = UrlParameter.Optional, CustomerID = UrlParameter.Optional } // Parameter defaults
    );

它将以您想要的方式构建URL。

(或者,您可以将参数重命名为GetOrderDetails操作到string OrderId,它会找到按您希望的方式格式化URL的路径。)

至于你的主要问题:

如何根据链接点击动态“加载”页面上的内容

有两种方法可以解决这个问题:

  • 发回页面。
  • AJAX /动态加载页面上HTML中的数据和元素。

在后置场景中:

在这种情况下,您的链接将全部转到构建包含主页中的订单列表的模型的操作,并且对于您单击的特定订单的详细信息,您将使用该订单的详细信息填充模型。然后你的ActionResult返回是相同的视图(或者至少看起来相同的视图),你的视图将使用PartialView Html帮助器来呈现细节。

OrderViewModel:

public class OrderViewModel
{
  public IList<Order> Orders {get;set;}
  public OrderDetail Details {get;set;}
}

OrderView.aspx:

<%@ Page Title="" Language="C#" Inherits="System.Web.Mvc.ViewPage<OrderViewModel>" %>
<%:Html.DisplayFor(m=>m.Orders)%> <%-- Displays the Table above listing orders --%>
<%:Html.DisplayFor(m=>m.Details)%> <%-- Displays your custom view of the details --%>

OrderController:

...
public ActionResult List()
{
  var model = new OrderViewModel { Orders = GetAllOrders(), Details = null };
  return View("OrderView", model);
}

public ActionResult GetOrderDetails(string OrderId)
{
  var model = new OrderViewModel { Orders = GetAllOrders(), Details = GetOrder(OrderId) };
  return View("OrderView", model);
}
...

在Ajax场景中:

Ajax场景基本相同,只是你在ajax调用中隐藏服务器往返,然后在返回数据中重新加载页面,或者只是一个包含你想要的内容的div来自html(或JSON) ajax电话。

Ajax方法的优点是您可以在不同的Controller上为要更新的页面的各个部分指定不同的Action。

答案 2 :(得分:1)

使用Url.Action在订单列表视图中构建网址。这将根据您的路由配置构建链接,因此当您更改配置时,您将不会获得损坏的链接。

至于出现在同一页面上,你可以使用某种形式的ajax。使用jquery,您可以在订单列表视图中找到类似这样的内容,连接到客户链接点击:

<script type="text\javascript">
    $('#result').load('<%= Url.Action("CustomerDetails", "Customer", 
             new { customerId = ViewModel["customerId"] }) %>');
</script>

<div id="result"/>

如果没有ajax,您的订单列表控制器需要一个参数,例如“displayCustomerId =”,这将告诉订单列表视图呈现客户详细信息:

<% if(ViewData["displayCustomerId"] != null) %>
    <% Html.RenderAction("CustomerDetails", "Customer", 
            new { customerId = ViewData["displayCustomerId"] }) %>
<% } %>

这两种技术都允许使用单独的控制器来提供视图中的相关数据,以便列出订单。