Вернуть список моделей
От: RPTAII2011  
Дата: 05.04.11 07:07
Оценка:
Есть главная модель которая содержит список моделей которые в свою очередь содержут список моделей....когда вывожу во вью все нормуль все работает....вношу изменения в текстовые поля пытаюсь отправить модель с изменениями но она возвращает пустой список моделей....в чем дело???

В представлении использую MainModel

public class MainModel()
{
public List<Model1>{get;set;}
}


public class Model1()
{
public List<Model2>{get;set;}
public properti1{get;set;}
...
public propertiX{get;set;}
}


public class Model2()
{

public properti1{get;set;}
...
public propertiX{get;set;}
}
Re: Вернуть список моделей
От: RushDevion Россия  
Дата: 05.04.11 08:35
Оценка: 3 (1)
Речь об MVC я так понимаю?
Неплохо было бы, конечно, на код View взглянуть для ясности.
Ну скорей всего дело в том, что MVC понятия не имет, как заполнять твой список Model из данных реквеста.
Нужно написать свой ModelBinder.
Пример тут
Re[2]: Вернуть список моделей
От: RPTAII2011  
Дата: 05.04.11 08:43
Оценка:
Здравствуйте, RushDevion, Вы писали:

RD>Речь об MVC я так понимаю?

RD>Неплохо было бы, конечно, на код View взглянуть для ясности.
RD>Ну скорей всего дело в том, что MVC понятия не имет, как заполнять твой список Model из данных реквеста.
RD>Нужно написать свой ModelBinder.
RD>Пример тут




<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<russian_promo.Models.MainModel>" %>
<%@ Import Namespace="russian_promo.Models" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Sape
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<% using (Html.BeginForm())
{ %>
<h2>Sape-задачи</h2>
<!--Таб меню-->

<table>
<tr>
<td> <%: Html.ActionLink("Добавить задачу", "SapeAdd", "Sape")%></td>
<td> <%: Html.ActionLink("Сохранить изменения", "SapeChangesSave", new { model=(MainModel)ViewData.Model })%></td>
<td> <%: Html.ActionLink("Оценка качества", "SapeManagerMurks", "Sape")%></td>
</tr>
</table>
<!--Таб меню-->
<br />
<input id="Submit1" type="submit" value="Сохранить" />
<br />

<%:Html.TextBoxFor(model=>model.str) %>
<%:Html.HiddenFor(model=>model.ListProject) %>
<table class="myTable">

<%for (int i = 0; i < ViewData.Model.ListProject.Count; i++)
{%>
<%Guid projectId = ViewData.Model.ListProject.ElementAt(i).ProjectId; %>
<%:Html.HiddenFor(model=>model.ListProject.ElementAt(i).ProjectId) %>
<tr>
<td >
<%:Html.DisplayTextFor(model => model.ListProject.ElementAt(i).ProjectName)%>
<%:Html.HiddenFor(model => model.ListProject.ElementAt(i).ProjectName)%>
</td>
<td >
<%:Html.ActionLink(ViewData.Model.ListProject.ElementAt(i).SAPEManager, "SapeManager", new { projectId = ViewData.Model.ListProject.ElementAt(i).ProjectId })%>
<%:Html.HiddenFor(model => model.ListProject.ElementAt(i).SAPEManager)%>
</td>
<td >
<%=Html.Encode(ViewData.Model.ListProject.ElementAt(i).SEO)%>
<%:Html.HiddenFor(model => model.ListProject.ElementAt(i).SEO)%>
</td>
<td class="MyTablePadding">
<table class="myTable1">
<%List<SapeTasks> SapeTaskForProject = (List<SapeTasks>)ViewData.Model.ListProject.ElementAt(i).ListProjectSape; %>
<%:Html.HiddenFor(model => model.ListProject.ElementAt(i).ListProjectSape)%>
<%for (int j = 0; j < SapeTaskForProject.Count; j++)
{%>
<tr>
<td>
<%=Html.Encode(SapeTaskForProject.ElementAt(j).DateFirstDay)%>
<%:Html.HiddenFor(model => model.ListProject.ElementAt(i).ListProjectSape.ElementAt(j).DateFirstDay)%>
</td>
<td>
<%:Html.ActionLink(SapeTaskForProject.ElementAt(j).TaskFile.ToString(), "SapeTask", new { SAPEtaskId = SapeTaskForProject.ElementAt(i).Id })%>
<%:Html.HiddenFor(model => model.ListProject.ElementAt(i).ListProjectSape.ElementAt(j).TaskFile)%>
</td>
<td>
<%=Html.Encode(SapeTaskForProject.ElementAt(j).CountLinks)%>
<%:Html.HiddenFor(model => model.ListProject.ElementAt(i).ListProjectSape.ElementAt(j).CountLinks)%>
</td>
<td>
всего
</td>
<td>
<%:Html.TextBoxFor(model => model.ListProject.ElementAt(i).ListProjectSape.ElementAt(j).LinkAddToday)%>
<%:Html.HiddenFor(model => model.ListProject.ElementAt(i).ListProjectSape.ElementAt(j).LinkAddToday)%>
</td>
<td>
<%:Html.TextBoxFor(model => model.ListProject.ElementAt(i).ListProjectSape.ElementAt(j).LinkDeleteToday)%>
<%:Html.HiddenFor(model => model.ListProject.ElementAt(i).ListProjectSape.ElementAt(j).LinkDeleteToday)%>
</td>
<td>
<%string Dateflag = SapeTaskForProject.ElementAt(j).DateStartBay.ToString();
string Datestatus = "";
switch (Dateflag)
{
case "01.01.0001 0:00:00":
Datestatus = "//-----//";
break;
default:
Datestatus = SapeTaskForProject.ElementAt(j).DateStartBay.ToString();
break;
}
%>
<%=Html.Encode(Datestatus)%>
<%:Html.HiddenFor(model => model.ListProject.ElementAt(i).ListProjectSape.ElementAt(j).DateStartBay)%>
</td>
<td>
<%string Dateflag1 = SapeTaskForProject.ElementAt(j).DateEndBay.ToString();
string Datestatus1 = "";
switch (Dateflag1)
{
case "01.01.0001 0:00:00":
Datestatus1 = "//-----//";
break;
default:
Datestatus1 = SapeTaskForProject.ElementAt(j).DateEndBay.ToString();
break;
}
%>
<%=Html.Encode(Datestatus1)%>
<%:Html.HiddenFor(model => model.ListProject.ElementAt(i).ListProjectSape.ElementAt(j).DateEndBay)%>
</td>
<td>
<%string Dateflag2 = SapeTaskForProject.ElementAt(j).DateLastDay.ToString();
string Datestatus2 = "";
switch (Dateflag2)
{
case "01.01.0001 0:00:00":
Datestatus2 = "//-----//";
break;
default:
Datestatus2 = SapeTaskForProject.ElementAt(j).DateLastDay.ToString();
break;
}
%>
<%=Html.Encode(Datestatus2)%>
<%:Html.HiddenFor(model => model.ListProject.ElementAt(i).ListProjectSape.ElementAt(j).DateLastDay)%>
</td>
<td>
<%int flag = SapeTaskForProject.ElementAt(j).status;
string status = "";
switch (flag)
{
case 0:
status = "Новая";
break;
case 1:
status = "В работе";
break;
case 2:
status = "На проверке";
break;
case 3:
status = "Завершено";
break;
}
%>
<%=Html.Encode(status)%>
<%:Html.HiddenFor(model => model.ListProject.ElementAt(i).ListProjectSape.ElementAt(j).status)%>
</td>
</tr>
<% } %>
</table>
</td>
</tr>
<% } %>
</table>
<%} %>
</asp:Content>
Re[3]: Вернуть список моделей
От: RushDevion Россия  
Дата: 05.04.11 10:07
Оценка: 3 (1)
Насколько мне удалось понять визуально это выглядит как таблица проектов для каждого из которых показывается список тасков.
Так, а какое поведение ожидается при нажатии кнопки "Сохранить"? Что все измененные названия проектов (о тасках пока не говорю) сохранятся
и в экшен придет правильно заполненный список проектов. Так не будет. Это слишком сложный биндинг для MVC. Придется писать свой ModelBinder.

Вообще во View много непонятного (а местами страшного ):

<%:Html.HiddenFor(model=>model.ListProject) %>
Что должно быть записано в hidden-поле? Список? Неа. MVC так не может.


<%for (int i = 0; i < ViewData.Model.ListProject.Count; i++) {%> и последующий ListProject.ElementAt(i)
Здесь лучше foreach использовать.


<%:Html.DisplayTextFor(model => model.ListProject.ElementAt(i).ProjectName)%>
<%:Html.HiddenFor(model => model.ListProject.ElementAt(i).ProjectName)%>
Зачем дублировать ProjectName hidden-полем? Да еще с тем же именем.


                         switch (Dateflag)
                                    {
                                        case "01.01.0001 0:00:00":
                                            Datestatus = "//-----//";
                                            break;                                      
                                    }
Не надо делать такие вещи во въю, иначе придется их дублировать во всех View, где потребуется аналогичная функциональность.
Сделай это либо хелпером, либо свойством ViewModel'и


Ну про хранение строки лучше хранить в ресурсах я уже молчу.

Вообще мне непонятно желание (если я конечно правильно все понял) сохранять все проекты сразу. Сделай список проектов. Сделай отдельное редактирование проекта и будет вам счастье.
Re[4]: Вернуть список моделей
От: RPTAII2011  
Дата: 05.04.11 10:29
Оценка:
На эти казусы не обращайте внимания это я уже от безысходности что только не пробовал)))))))))).....вообще по нажатию на сохранить должно произойти следующее......мы в таски вносим какие либо изменения не обязательно во все....выборочно куда понадобиться и потом сохраняем изменения.....я хотел после отправки в контроллере пробежаться циклом по модели отследить изменения и сохранить но список моделей возвращается пустой
Re[5]: Вернуть список моделей
От: RushDevion Россия  
Дата: 05.04.11 10:51
Оценка: 3 (1)
Здравствуйте, RPTAII2011, Вы писали:

RPT>вообще по нажатию на сохранить должно произойти следующее......мы в таски вносим какие либо изменения не обязательно во все....выборочно куда понадобиться и потом сохраняем изменения.....я хотел после отправки в контроллере пробежаться циклом по модели отследить изменения и сохранить но список моделей возвращается пустой


Это возможно. Но как я уже сказал (дважды даже) нужно писать свой биндер. С вашим уровеннем в MVC — это сложная задача.
Поэтому я бы порекомендовал изменить пользовательский интерфейс.
Сделайте список проектов в виде таблицы. Сделайте ссылку "редактировать" для проекта. По щелчку на нее — выдавайте View редактирования
проекта. В этом view будет список тасков. Редактирование таска — также в отдельном view. Все просто.
Re[6]: Вернуть список моделей
От: RPTAII2011  
Дата: 05.04.11 11:06
Оценка:
RD>Сделайте список проектов в виде таблицы. Сделайте ссылку "редактировать" для проекта. По щелчку на нее — выдавайте View редактирования
RD>проекта. В этом view будет список тасков. Редактирование таска — также в отдельном view. Все просто.


Да я бы с радостью так сделал))))))...только вот задача стоит именно такая...если не сложно могли бы объяснить как это сделать, а то про мой уровень вы верно подметили.... чуть больше недели прошло как я с web forms на mvc перешел
Re[7]: Вернуть список моделей
От: RPTAII2011  
Дата: 05.04.11 11:16
Оценка:
Я нашел пример реализации только у меня возникли вопросы
1.//i don't know how to bind to the list property
fund.FundItems[0].Catalogue.Id = controllerContext.HttpContext.Request.Form["FundItem.Catalogue.Id"];
как именно для списка все это сделать
2.и что мне потом с этим биндером делать когда я его напишу

public class FundModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
throw new NotImplementedException();
}
public object GetValue(ControllerContext controllerContext, string modelName, Type modelType, ModelStateDictionary modelState)
{
var fund = new Fund();
fund.Id = int.Parse(controllerContext.HttpContext.Request.Form["Id"]);
fund.Name = controllerContext.HttpContext.Request.Form["Name"];
//i don't know how to bind to the list property
fund.FundItems[0].Catalogue.Id = controllerContext.HttpContext.Request.Form["FundItem.Catalogue.Id"];
return fund;
}
}
Re[8]: Вернуть список моделей
От: RushDevion Россия  
Дата: 05.04.11 12:04
Оценка: 3 (1)
1) Для начала следует понять, зачем вообще нужен биндер.
Когда пользователь сабмитит форму, браузер формирует POST запрос.
Этот запрос можно посмотреть например через Fidler или Firebug (Firefox). Рекомендую поставить — очень полезный тул для разработки ModelBinder'ов и не толька
Так вот, если посмотреть, что же там браузер шлет, то можно увидеть строку из имен/значений полей.
Т.е. если во View это было HiddenFor(model=>model.Id), TextBoxFor(model=>model.Description), то в POST это будет id=1&Description=ТекстПользователя&.
И стандартный биндинг MVC легко справляется с такими простыми вещами.
А вот для списков не все сложнее. Почитайте вот тут пример.
Там же, кстати, написано, как обойтись без биндера (сам я это не проверял). Основная идея в том, что поля должны отличаться по именам, т.е.
в POST это должно быть что-то вроде id1=1&Description1=ТекстПользователя&id2=1&Description2=ТекстПользователя& и т.д. Тогда значения
легко достанутся в биндере.
Просто на то чтобы написать полноценный пример биндера у меня сейчас нет времени.

2) Сами биндеры регистрируются в файле global.asax (метод Application_Start )
ModelBinders.Binders[typeof( FundModelBinder )] = new FundModelBinder();
Re[9]: Вернуть список моделей
От: RPTAII2011  
Дата: 05.04.11 12:15
Оценка:
Спасибо большое буду разбираться)))))))))))))
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.