Как отделить реляционные данные MVC

#asp.net-mvc #asp.net-mvc-3 #asp.net-mvc-routing

#asp.net-mvc #asp.net-mvc-3 #asp.net-mvc-routing

Вопрос:

Рассмотрим этот сценарий:

Я хочу создать MVC-приложение для базы данных Northwind. Я хочу иметь представление, в котором перечислены некоторые заказы, и я хочу создать ссылки для CustomerID и EmployeeID и ссылку details для [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>
  

глобальный.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?

И почему URL отображается таким образом, когда я нажимаю на ссылки OrderDetails:

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

Я хочу, чтобы URL отображался таким образом:

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

Комментарии:

1. Еще не поздно попытаться решить это в представлении. Разве вы не должны были решить это раньше, в контроллере. Представление просто отображает данные, поэтому при правильной модели или даже viewmodel представление становится тривиальной интерпретацией.

Ответ №1:

На ваш вопрос о маршрутизации:

если вы настроили маршрут следующим образом:

     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 возвращает тот же вид (или, по крайней мере, тот, который выглядит одинаково), и ваш вид будет использовать HTML-помощник PartialView для отображения деталей.

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 заключается в том, что вы могли бы указать другое действие на другом контроллере для различных частей страницы, которые вы хотели обновить.

Комментарии:

1. Спасибо, но как я могу загрузить детали на той же странице?H

2. Не видя вашего контроллера (ов) и модели (ов), трудно сказать… Вы можете сделать это либо с помощью AJAX, либо с помощью post-backs… Я расширю свой ответ.

3. спасибо, но мой главный вопрос remain.in полученное нами представление наследуется=»System.Web.Mvc.ViewPage<IEnumerable<My_MVC_Samples. Модели. Порядок>>» и это говорит нам, от какого объекта зависит наше представление. хорошо, как мы можем показать детали заказа (объект OrderDetails) в представлении, которые наследуются от объекта Order?

4. В вашей модели может быть как свойство Order, так и свойство OrderDetails. Или, если вы сделали это с помощью javascript и ajax, вы могли бы забыть Модель для деталей заказа и просто создать детали из JSON-представления модели details.

5. Я не хочу использовать Ajax. Я думаю, что с помощью Ajax мы обходим проблему, а не решаем ее. Можете ли вы показать мне короткий пример того, что вы говорите?

Ответ №2:

Nima,
вы можете сделать это с помощью частичных представлений или действия рендеринга и json для отображения данных
основной пример приведен здесь:http://www.asp.net/mvc/tutorials/iteration-7-add-ajax-functionality-cs

или очень популярный вариант — отобразить действие для задачи в jquery.dialog()

зависит от вас, каким способом вы хотите выполнить cpo


исправлено:

Виноват. С точки зрения логики, это как:
Это зависит только от вас, каким путем вы хотите пойти. (С моей точки зрения)

Преимущества разделения логики заключаются в :

  1. легко понять, поскольку контроллер связан только с действиями, например, для заказов
  2. Может использоваться в большем количестве мест, если вам нужно
  3. Легко тестировать только небольшие элементы, например, один тестовый набор / приспособление для контроллера только для заказов
  4. Полезно для более сложных проектов

С другой стороны

  1. Храните все в одном контроллере и разделите логику по регионам
  2. Все собрано вместе, легко увидеть другие методы и то, что они делают

Надеюсь, это то, что вы искали
cpo

Комментарии:

1. Спасибо, но моя проблема в том, как отделить контроллеры и просмотр.

2. Вы не можете просто добавить форму вокруг объекта, который хотите отобразить, и опубликовать в разных местах? например, Html.BeginForm (спецификация вашего маршрута здесь)

3. Я думаю, вы неправильно поняли мой вопрос. Я хочу знать, должен ли я создать контроллер для заказов, Customers и OrderDetails?

4. смотрите мой пересмотренный ответ (надеюсь, я знаю, что вы ищете сейчас :))