11 / 10 / 8
Регистрация: 06.07.2015
Сообщений: 75
1

Строго-типизированное представление. Как оно работает?

16.02.2017, 21:45. Показов 3002. Ответов 28
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Всем Доброго времени суток.
Никак не могу разобраться со строго-типизированными представлениями.
Есть представление типа:
C#
1
2
3
@model Models.ResetPasswordViewModel
@using (Html.BeginForm("ResetPassword", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
// код представления
Есть контроллер типа:
C#
1
2
3
4
5
6
7
8
9
10
11
[HttpPost]      
public async Task<ActionResult> ResetPassword(ResetPasswordViewModel model)
{
    // некий код
    if (user != null)
    {               
        return RedirectToAction("ResetPasswordConfirmation", "Account");                
    }           
    ModelState.AddModelError("", "Пользователь с заданным именем не найден.");
    return View();  // в чем отличие от return View(model)
}
Вопросы:
1. Чем отличается return View() от return View(model) в контроллере?
2. Каким образом передается ModelState в представление? Почему при возврате RedirectToAction он не передается, а при PartialView и View передается. Выяснил путем тыканья, в других случаях также выяснять?
3. На странице используется строго-типизированное представление указанное выше в виде @RenderBody, а также пара строго-типизированных представлений в виде @Html.Partial. Как их подружить? При попытке сделать так return View(model) другое представление ругается что model для возврата не соответствует с другими представлениями. Отсюда вопрос а можно сделать условие чтоб если не твое, то и не трогай!? Типа такого:
C#
1
if (model.GetType() ==  ResetPasswordViewModel) @model Models.ResetPasswordViewModel;
но чтобы объявление все равно было (@model Models.ResetPasswordViewModel), но model оно бы не использовало из контроллера.

Как то так. прошу помощи так как сам уже вымотался во всем этом разбираться.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
16.02.2017, 21:45
Ответы с готовыми решениями:

Как передать из одного контроллера объект модели в строго типизированное представление другого контроллера
Есть строго типизированное представление в контроллере Main, в методе ListOrders. Как в него можно...

Как оно работает ?
Привет, возник такой вопрос - как функционирует win10? Суть вопроса в том как осуществляется связь...

Как оно работает?
Народ, объясните мне, как вот это работает? 2hASOre63Nk

КАК оно работает?
Раскрутил я старый налобный фонарь с аккумом. Там был сам аккум, кнопочка, и платка. Платка меня...

28
64 / 64 / 35
Регистрация: 14.12.2015
Сообщений: 145
17.02.2017, 09:33 2
Silvestor, привет! Я не эксперт, но попытаюсь объяснить как сам это понимаю.
1)return View() и return View(model) отличаются тем, что в первом случае не передаётся модель (спасибо, кэп). Но в обоих случаях передаётся, например, ModelState. То есть при возникновении ошибки, мы и в первом и во втором случае сможем передать её на вьюху. Просто в первом случае она будет не заполнена.
2) Тут могу ошибаться, но думается, что ModelState живёт до тех пор, пока мы работаем с конкретной моделью. При RedirectToAction мы вообще вызываем другой метод контроллера и поэтому ни о каком ModelState нет речи.
3) Тут немного неясно, но предположу, что Вам нужно использовать более комплексную ViewModel, а в отдельные Partial при необходимости передавать что-то типа
C#
1
@Html.Partial("_YourPartialViewName", Model.CustomList)// тут CustomList - новый параметр в ResetPasswordViewModel
0
11 / 10 / 8
Регистрация: 06.07.2015
Сообщений: 75
17.02.2017, 12:48  [ТС] 3
Спасибо. Но:
1. Не все так просто. Хотел бы согласится, но мучает один вопрос, в случае с return View() данные модели тоже передаются неявно в представление. Собственно от чего вопрос и возник. Если вызвать return View() в POST методе контроллера, то данные модели также передадутся в представление (хоть и не все, пароли не передаются) и будут в разметке в полях инпут. Как я примерно это понимаю здесь возможно опять используется ModelState, и из него данные модели пишутся в разметку, а не из модели как таковой. Естественно если в случае с return View() в представлении обратится к свойству модели, скажем так @Model.Login, то будет ошибка, в отличии от return View(model).
2. Я как понимаю он живет всегда и в любом методе контроллера, но вот передавать его или нет это уже решает среда. А вот как она решает, а бог ее знает. По логике конечно все что выше написано верно, но....
3. Смысл в том, что у меня на одной странице несколько форм, каждая из своего частичного представления, со своим model. Если заполнять формы и передавать данные то все ок. Но если в контроллере вызвать return View(model), то в одном из частичных представлений вылетит ошибка со словами что переданная модель не соответствует той которая используется в нем. Смысл в том что когда мы передаем return View(model), то все три представления пытаются обработать переданную модель, хотя предназначается она тому представлению из которого была сформирована.
0
3458 / 2470 / 695
Регистрация: 02.08.2011
Сообщений: 6,692
17.02.2017, 13:19 4
Цитата Сообщение от Silvestor Посмотреть сообщение
тоже передаются неявно в представление.
Почему вы так решили?
Цитата Сообщение от Silvestor Посмотреть сообщение
Естественно если в случае с return View() в представлении обратится к свойству модели, скажем так @Model.Login, то будет ошибка
Верно, потому что модель не передается.

Цитата Сообщение от Silvestor Посмотреть сообщение
return View(model) другое представление ругается что model для возврата не соответствует с другими представлениями
попробуйте вернуть PartialView(model).

Добавлено через 8 минут
Partial View были созданы для асинхронных запросов, то есть на сервере вполне может быть такая логика:
C#
1
2
3
4
5
6
7
8
9
10
[HttpPost]      
public async Task<ActionResult> ResetPassword(ResetPasswordViewModel model)
{
    // some logic
    // then
   if (Request.IsAjaxtRequest)
       return PartialView(model)        
    // либо non-ajax
    return View(model);
}
Ятп, вы выполняете синхронный запрос из PartialView, который соответствует родительской вьюхе (с другой моделью).
0
11 / 10 / 8
Регистрация: 06.07.2015
Сообщений: 75
17.02.2017, 20:19  [ТС] 5
Цитата Сообщение от IamRain Посмотреть сообщение
Почему вы так решили?
Может не совсем так выразился. Передаются данные модели, которую пользователь заполнил в форме и передал на сервер.
Посидев с отладчиком разобрался как это работает:
При отправке данных формы на сервер, в методе обработчике POST запроса из контроллера формируется ModelState, который содержит в себе коллекцию данных формы. Если заново вызвать тоже представление (ощибки передать, ну или данные какие затребовать дополнительно) вызовами View() или View(model), представление, а именно поля формы будут заполнены данными из ModelState, в случае если имена совпадают. При этом если мы перед вызовом View(model) изменили некоторые данные в model, то поля формы все равно будут получать значения из ModelState, и только если в ModelState нет подходящих значений то используются данные из model. Код из внетренностей MVC:
C#
1
2
3
4
// Получить value для поля input из ModelState
string attemptedValue = (string)htmlHelper.GetModelStateValue(fullName, typeof(string));
// Проверить attemptedValue и если пуст взять model, в данном случае valueParameter
tagBuilder.MergeAttribute("value", attemptedValue ?? ((useViewData) ? htmlHelper.EvalString(fullName, format) : valueParameter), isExplicitValue);
Цитата Сообщение от IamRain Посмотреть сообщение
попробуйте вернуть PartialView(model).
Не совсем то что надо.
Там где нужны были данные модели для формы и через View() можно получить. А в случае генерации страницы Error.cshtml и передачи текста сообщения об ошибке в модели, PartialView(model) не поможет.
0
3458 / 2470 / 695
Регистрация: 02.08.2011
Сообщений: 6,692
17.02.2017, 20:45 6
Цитата Сообщение от Silvestor Посмотреть сообщение
Не совсем то что надо.
Так непонятно, что вам нужно. PartialView предназначены для асинхронных запросов (ajax).
Обычно делают так: в основной вьюхе при первой загрузке в razor-е вызывают методы для всех PartialView (Htm.RenderAction, либо Html.PartialView, как-то так). А Partial потом уже сами по себе обновляются по ajax-у, вызывая свои собственные методы через Ajax.BeginForm.
0
11 / 10 / 8
Регистрация: 06.07.2015
Сообщений: 75
17.02.2017, 22:09  [ТС] 7
С частичными представлениями все понятно, у меня собственно так и сделано для модальных окон регистрации и авторизации, которые общие на все страницы и подгружаются вместе с _layout.chtml.
Но вот допустим есть у меня представление Error.chtml которое не частичное и рендерится через вызов view("Error"), в случае каких либо ошибок в контроллере. Задумал я к этому пердставлению прилепить детальную информацию об ошибке через view_model с полем message. Чтобы было типа такого:
C#
1
return View("Error", new ErrorModel{message = "Нет доступа к диску"});
Но беда в том, что переданная модель конфликтует с моделями из частичных представлений.
Нет, можно конечно ошибку и через ViewBag передавать, но как то это не красиво получается. Подумал может есть возможность подружить разные модели на одной странице.
0
2735 / 2041 / 380
Регистрация: 22.07.2011
Сообщений: 7,731
18.02.2017, 01:23 8
Цитата Сообщение от Silvestor Посмотреть сообщение
Но беда в том, что переданная модель конфликтует с моделями из частичных представлений.
Для этого придуманы пространства имен. , без явного указания которых в таком случае , проект даже не скомпилируется в студии.
0
11 / 10 / 8
Регистрация: 06.07.2015
Сообщений: 75
18.02.2017, 11:00  [ТС] 9
Цитата Сообщение от sau Посмотреть сообщение
Для этого придуманы пространства имен. , без явного указания которых в таком случае , проект даже не скомпилируется в студии.
А это здесь при чем, не понял. Вы может какие-то другие пространства имен имеете в виду.
Насколько я понимаю, при задании скажем @model Models.ResetPasswordViewModel в представлении оно ожидает что ему будет передана именно эта модель, и в случае если в поток обработки представлений передается другая модель с данными, то возникает ошибка несовместимости типов, хоть в разные пространства имен помести.
0
Эксперт .NET
12062 / 8371 / 1280
Регистрация: 21.01.2016
Сообщений: 31,563
18.02.2017, 11:08 10
Цитата Сообщение от Silvestor Посмотреть сообщение
Но беда в том, что переданная модель конфликтует с моделями из частичных представлений.
Это вдруг как так получается?..
0
11 / 10 / 8
Регистрация: 06.07.2015
Сообщений: 75
18.02.2017, 11:41  [ТС] 11
Вот как:
The model item passed into the dictionary is of type 'WebAppServer.Models.ResetPasswordViewModel', but this dictionary requires a model item of type 'WebAppServer.Models.RegisterViewModel'.
Ошибка источника:
Строка 21: <div class="modal-content" id="switchRegisterModal">
Строка 22:
Строка 23: @Html.Partial("_RegisterModalPartial")
Строка 24:
Строка 25: </div>
Исходный файл: c:\Users\Admin\Documents\Visual Studio 2013\Projects\WebAppServer\WebAppServer\Views\Shared\_Layout.cshtml Строка: 23
В частичном используется модель - RegisterViewModel.
А в _Layout через @RenderBody() передается ResetPasswordViewModel.

Схематично _Layout:
C#
1
2
3
4
5
6
7
...
@Html.Partial("_RegisterModalPartial")
...
 @Html.Partial("_LoginModalPartial")
...
 @RenderBody()
...
В рендер боди передается основное представление страницы в котором используется форма для заполнения инфы на сброс пароля, соответственно есть своя модель. И если передать модель через return view(model) то частичные представления тоже стараются ей воспользоваться.
0
1489 / 1037 / 146
Регистрация: 01.10.2009
Сообщений: 3,484
Записей в блоге: 1
18.02.2017, 12:22 12
Silvestor, ибо передавайте в контроллере return viewpartial а в мастере html.Action(), попробуйте
0
3458 / 2470 / 695
Регистрация: 02.08.2011
Сообщений: 6,692
18.02.2017, 13:23 13
Цитата Сообщение от Silvestor Посмотреть сообщение
Вот как:
Тут говорится, что вы пытаетесь засунуть ResetPasswordViewModel вместо RegisterViewModel.
Покажите View для сброса пароля.
0
11 / 10 / 8
Регистрация: 06.07.2015
Сообщений: 75
18.02.2017, 13:39  [ТС] 14
Цитата Сообщение от XIST Посмотреть сообщение
ибо передавайте в контроллере return viewpartial а в мастере html.Action(), попробуйте
Не понял, как вы предлагаете реализовать. return viewpartial вернет же только частичное представление. Ajax использовать?
Поподробней можно пожалуйста.

Добавлено через 1 минуту
Цитата Сообщение от IamRain Посмотреть сообщение
Покажите View для сброса пароля.
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
@model WebAppServer.Models.ResetPasswordViewModel
@{
    ViewBag.Title = "Сброс пароля";
}
 
<h2>@ViewBag.Title.</h2>
 
@using (Html.BeginForm("ResetPassword", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
{
    @Html.AntiForgeryToken()
    <hr/>
    @Html.ValidationSummary(true, null, new { @class = "text-danger" })
    @Html.HiddenFor(model => model.Code)
    <div class="form-group">
        @Html.LabelFor(m => m.Login, "Имя:", new { @class = "col-sm-3 control-label" })
        <div class="col-sm-9">
            @Html.TextBoxFor(m => m.Login, new { @class = "form-control" })
        </div>
        <div class="col-sm-12">
            @Html.ValidationMessageFor(m => m.Login, null, new { @class = "text-danger pull-right" })
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(m => m.Password, "Пароль:", new { @class = "col-sm-3 control-label" })
        <div class="col-sm-9">
            @Html.PasswordFor(m => m.Password, new { @class = "form-control" })
        </div>
        <div class="col-sm-12">
            @Html.ValidationMessageFor(m => m.Password, null, new { @class = "text-danger pull-right" })
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(m => m.ConfirmPassword, "Подтвердить пароль:", new { @class = "col-sm-3 control-label" })
        <div class="col-sm-9">
            @Html.PasswordFor(m => m.ConfirmPassword, new { @class = "form-control" })
        </div>
        <div class="col-sm-12">
            @Html.ValidationMessageFor(m => m.ConfirmPassword, null, new { @class = "text-danger pull-right" })
        </div>
    </div>
    <div class="form-group">
        <div class="col-sm-offset-3 col-sm-9">
            <input type="submit" class="btn btn-default" value="Сбросить" />
        </div>
    </div>
}
0
Эксперт .NET
12062 / 8371 / 1280
Регистрация: 21.01.2016
Сообщений: 31,563
18.02.2017, 13:58 15
Цитата Сообщение от Silvestor Посмотреть сообщение
В частичном используется модель - RegisterViewModel.
А в _Layout через @RenderBody() передается ResetPasswordViewModel.
Ну так, а чего ты хотел?)) Свормируй отдельную модель представления, в которую влож нужные для этих partial модели и передавай их им явно.
0
11 / 10 / 8
Регистрация: 06.07.2015
Сообщений: 75
18.02.2017, 14:32  [ТС] 16
Цитата Сообщение от Usaga Посмотреть сообщение
Свормируй отдельную модель представления, в которую влож нужные для этих partial модели и передавай их им явно.
Сформированы модели для них, и используются при случае. Но в данном случае мне не надо в эти партиалы что либо передавать.
0
Эксперт .NET
12062 / 8371 / 1280
Регистрация: 21.01.2016
Сообщений: 31,563
18.02.2017, 16:51 17
Silvestor, тогда передавай туда null, а в самих partial делай проверку. Иначе фигня выходит.
0
11 / 10 / 8
Регистрация: 06.07.2015
Сообщений: 75
18.02.2017, 21:32  [ТС] 18
Цитата Сообщение от Usaga Посмотреть сообщение
тогда передавай туда null, а в самих partial делай проверку. Иначе фигня выходит.
Замечательно, так и хочу сделать, как так сделать?
Можно поподробней?
0
Эксперт .NET
12062 / 8371 / 1280
Регистрация: 21.01.2016
Сообщений: 31,563
19.02.2017, 05:51 19
Silvestor, что-то вопрос несерьёзный. Почитай про Partials. Ссылка на модель представления передаётся вторым аргументом, после имени\пути к частичному представлению. Можно передать либо Null, либо пустую модель представления.
0
11 / 10 / 8
Регистрация: 06.07.2015
Сообщений: 75
19.02.2017, 16:45  [ТС] 20
Usaga, что такое Partial View мне понятно, и использовать их умею, писал же уже.
Мне не понятно вот это,
Цитата Сообщение от Usaga Посмотреть сообщение
а в самих partial делай проверку
что вы имеете ввиду.
Может мы просто о разном говорим.
0
19.02.2017, 16:45
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
19.02.2017, 16:45
Помогаю со студенческими работами здесь

Typeid-как оно работает
Добрый день.Я встречала,что typeid используется для определения типа в том случае,когда у нас есть...

Pascal Подкажите как оно работает?
var x,y,z: real; sign: char; begin while True do begin write('sign: '); readln(sign);...

Как оно работает (контекстное меню)?
Всем, добрый день, программисты. Очень рад общению с Вами:) Я новичок в Вашем деле... и хочу стать...

Shared object или как оно работает?
В общем, растолкуйте уважаемые, на счет этих shared object библиотек, они же *.so Вот с...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru