ASP.NET MVC 2: проблемы с созданием представления Master-Detail

У меня сейчас проблемы с созданием страницы Master-Detail в проекте ASP.NET MVC 2. Этот проект использует Entity Framework OR/M для сопоставления таблиц. Я использую пользовательскую CategoryModel, которая передает другой список объектов. Я упростил Модель для презентационных целей:

    public class CategoryModel {
    public Category Category { get; set; }
    public IEnumerable<CategoryDescription> CategoryDescriptions { get; set; }
    }

CategoryDescription – это набор описаний, основанных на языке культуры, для каждой Категории.

Я передаю CategoryModel своему контроллеру [опять же, метод контроллера Edit был упрощен для целей презентации]:

        // CategoryModel constructor
        CategoryModel categoryModel = new CategoryModel()
        {
            Category = (from c in bo.Categories where c.CategoryID == categoryId select c) as Category,
            CategoryDescriptions = bo.CategoryDescriptions.Where(p => p.CategoryID == categoryId).OrderBy(p => p.Language == "en")
        };
        return View(categoryModel);

После этого я отправляю данные в свое представление, которое, в свою очередь, попытается отобразить PartialView для каждой имеющейся у меня CategoryDescription. Вот здесь я провалился [отображается только часть представления, часть, показывающая объект Category, работает нормально]:

        <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<InnVue.Globe.Models.CategoryModel>" %>
    <%@ Import Namespace="InnVue.Globe.Models" %>

    <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
        <%: ViewContext.RouteData.Values["Action"] %> Category
    </asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <h2><%: ViewContext.RouteData.Values["Action"] %> Category</h2>

    <% Html.EnableClientValidation(); %>
    <% using (Html.BeginForm()) {%>
        <%: Html.ValidationSummary(true) %>

        <fieldset>
            <legend>CategoryDescription</legend>
            <% foreach (var catdes in Model.CategoryDescriptions) { %>
                <% Html.RenderPartial("CategoryDescriptions", catdes); %>
            <% } %>
            <% Html.RenderPartial("CategoryDescriptions", Model.CategoryDescriptions, new ViewDataDictionary()); %>
            <p>
                <input type="submit" value="Save" />
            </p>
        </fieldset>
    <% } %>

    <div>
        <%: Html.ActionLink("Back to List", "Index") %>
    </div>

</asp:Content>

Проблема, с которой я столкнулся сейчас, связана с методом RenderPartial, который приводит к сбою моего приложения каждый раз, когда я пытаюсь передать через него данные.

Я пытался изменить тег Inherits на несколько типов, но это не решило проблему. Если я не передам никаких данных с помощью метода RenderPartial htmlhelper, страница загружается нормально.

Я пробовал несколько предложений на форумах, но не смог найти ответ на решение этой проблемы. Единственное ограничение, которое у меня есть здесь для извлечения данных из PartialView, — не использовать ViewData[] словарь от моей компании по многим очевидным причинам.

Спасибо за ваше время, люди, и извините за мой английский, я носитель французского языка из Канады, если есть какие-то опечатки, извините заранее!

EDIT 01/10 : The reason why there's one RenderPartial outside the loop is for a new input box for adding description content, but there's logic in the postback edit method of my controller to take care of this. the RenderPartial inside the loop is there to let the user edit existing descriptions of that category. Starting to make the loop work is the key here, I've only made a scaffolded PartialView for test purposes, I can't even load an empty "

Hello World

" if I pass data to the PartialView. I'll add in code of the PartialView, even if I'm not sure of which class it should inherit :

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<InnVue.Globe.Models.CategoryModel>" %>

<% using (Html.BeginForm()) {%>
    <%: Html.ValidationSummary(true) %>

    <fieldset>
        <legend>Fields</legend>
        <p>Hello World !</p>
        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>

<% } %>

<div>
    <%: Html.ActionLink("Back to List", "Index") %>
</div>

person LoganWolfer    schedule 01.10.2010    source источник
comment
У вас тут всякие проблемы. У вас не может быть формы внутри другой формы, и вы не можете передать частичное представление типа данных, для которого оно не предназначено. Ваш частичный вид также имеет тот же тип, что и ваш основной вид. Ваш частичный вид должен быть типа CategoryDescription, и вам нужно удалить второй партиал рендеринга и реализовать его другим способом.   -  person Nick Larsen    schedule 02.10.2010
comment
Спасибо, Ник, очень помогло! знак равно   -  person LoganWolfer    schedule 04.10.2010


Ответы (2)


Похоже, вы дважды вызываете один и тот же метод частичного рендеринга, один раз передавая его с типом данных CategoryDescription, а другой раз передавая ему модель с типом IEnumerable<CategoryDescription>. Вы пытались закомментировать тот, который не передает правильный тип данных для представления?

Попробуйте что-то вроде этого:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<InnVue.Globe.Models.CategoryModel>" %>
    <%@ Import Namespace="InnVue.Globe.Models" %>

    <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
        <%: ViewContext.RouteData.Values["Action"] %> Category
    </asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <h2><%: ViewContext.RouteData.Values["Action"] %> Category</h2>

    <% Html.EnableClientValidation(); %>
    <% using (Html.BeginForm()) {%>
        <%: Html.ValidationSummary(true) %>

        <fieldset>
            <legend>CategoryDescription</legend>
            <% foreach (var catdes in Model.CategoryDescriptions) { %>
                <% Html.RenderPartial("CategoryDescriptions", catdes); %>
            <% } %>

            <p>
                <input type="submit" value="Save" />
            </p>
        </fieldset>
    <% } %>

    <div>
        <%: Html.ActionLink("Back to List", "Index") %>
    </div>

</asp:Content>

И используйте это как частичное представление:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<InnVue.Globe.Models.CategoryModel>" %>

<%: Html.EditorFor(m => m) %>
person Nick Larsen    schedule 01.10.2010

Спасибо NickLarsen за помощь, ваш комментарий помог мне понять, что я делаю не так.

Причиной проблемы было наследование моего частичного просмотра.

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<InnVue.Globe.Models.CategoryDescription>" %>

Было ли это решением моей проблемы, я не очень понимал строго типизированные представления, и это привело меня к бесцельному блужданию ^^'

Что касается двойного RenderPartial в моем представлении Edit, это необходимо, так как я хочу иметь новое поле для ввода новых данных независимо от того, в CategoryDescription уже есть строки данных или нет.

Вот окончательный набор полей для тех, кому интересно, как я сделал свою форму Master-Detail:

        <fieldset>
        <legend>CategoryDescription</legend>
        <% foreach (var catdes in Model.CategoryDescriptions) { %>
            <% Html.RenderPartial("CategoryDescription", catdes); %>
        <% } %>
        <% 
            CategoryDescription emptyCatDes = new CategoryDescription();
            Html.RenderPartial("CategoryDescription", emptyCatDes, new ViewDataDictionary()); %>
    </fieldset>

Я еще не знаю, эффективно ли это на 100 %, но вся информация сейчас правильно отображается в моем Просмотре.

Всем удачи, еще раз спасибо за помощь NickLarsen!

person LoganWolfer    schedule 04.10.2010