Как мне инкапсулировать форму / публикацию / проверку [/ редирект] в ViewUserControl в ASP.Net MVC 2
Короткая версия: нужен ViewUserControl (т. Е. Форма входа), чтобы публиковать сообщения для себя и иметь возможность перенаправлять (т. Е. При успешном входе в систему) или возвращать исходное представление (т. Е. Home/Index) со сводной информацией о проверке и не мешать другим ViewUserControls стр.
Кроме того, HomeController/Index должен иметь минимальные знания о внутренней работе формы входа. В идеале, Html.RenderAction("Логин","Пользователь") или аналогичный - это все, что требуется.
На данный момент застрял на перенаправлении даёт "Дочерним действиям не разрешено выполнять действия перенаправления". Я знаю, почему, но мне интересно, есть ли способ обойти это или иным образом, я должен это делать.
Детали того, чего я пытаюсь достичь:
- инкапсулируйте форму логина (или любую форму) для повторного использования на сайте
- пост для себя
- при неудачном входе в систему / проверке показать исходную страницу со сводной информацией о проверке
- (некоторые могут поспорить, что нужно просто публиковать на странице входа в систему и показывать там Сводную информацию о проверке; если то, что я пытаюсь достичь, невозможно, я просто пойду по этому пути)
- при успешном входе в систему перенаправьте в /App/Home/Index
- также хочу:
- придерживаться принципов PRG
- избегать ajax
- сохраняйте форму входа (UserController.Login()) как можно более инкапсулированной; Избегайте реализации HomeController.Login(), так как форма входа может появиться в другом месте.
Все кроме перенаправления работает. Мой подход до сих пор был:
Home/Index
включает в себя форму входа:<%Html.RenderAction("Login","User");%>
User/Login ViewUserControl<UserLoginViewModel>
включает в себя:
using(Html.BeginForm()){}
- включает скрытое поле формы
"userlogin"="1"
public class UserController : BaseController {
...
[AcceptPostWhenFieldExists(FieldName = "userlogin")]
public ActionResult Login(UserLoginViewModel model, FormCollection form){
if (ModelState.IsValid) {
if(checkUserCredentials()) {
setUserCredentials()
return this.RedirectToAction<Areas.App.Controllers.HomeController>(x => x.Index());
}
else {
return View();
}
}
...
}
Прекрасно работает, когда: ModelState или User Credentials дают сбой - return View() действительно уступает Home / Index и отображает соответствующую сводку проверки.
(У меня есть форма регистрации на той же странице, использующая ту же структуру. Сводка проверки каждой формы отображается только при отправке этой формы.)
Сбой, когда: ModelState и User Credentials valid - RedirectToAction<>() выдает следующую ошибку:
"Дочерним действиям запрещено выполнять действия перенаправления".
Кажется, что в классические дни ASP, это было бы решено с Response.Buffer=True
, Есть ли эквивалентная настройка или обходной путь сейчас?
Кстати, работает: ASP.Net 4, MVC 2, VS 2010, Dev / Debugging Web Server
Я надеюсь, что все это имеет смысл.
Итак, каковы мои варианты? Или где я иду не так в моем подходе? ТИА!
2 ответа
Я бы пошел с частичным представлением (например, "_Login.cshtml" или "_Login.ascx"), который может быть размещен на MasterPage/_Layout. Внутри частичного представления вы пишете тег формы, который публикует действие на контроллере (скажем, "AuthController" и действие "LogIn"). Чтобы вспомнить, откуда вы пришли
Вот как действие может выглядеть так:
public ActionResult LogIn(string username, string password)
// name the id's of the form elements as the parameters
{
if(YouAuthMethodHere(username, password))
{
return View("Welcome");
}
else
{
return Redirect(HttpContext.Current.Request.Referer.AbsolutUri);
}
}
После успешной аутентификации пользователя возвращается представление с именем "Welcome.cshtml"/"Welcome.aspx", в противном случае оно перенаправляется из того места, где была отправлена форма.
Примечание: реферер может быть нулевым (например, если не браузер, такой как fiddler или скрипт делает запрос), поэтому остается немного обработки ошибок.
Древний вопрос, но это в основном то же самое, что я делаю сейчас, и мои поиски все еще не выявили ответов, которые соответствуют всем критериям; Я не понимаю, почему так трудно полностью инкапсулировать процесс входа в систему, как это, но, возможно, я просто пропускаю четко написанный пример.
Мое решение, которое работает отлично, это просто использовать старый стандарт
System.Web.HttpContext.Current.Response.Redirect(url, true);
... в контроллере для процесса входа в систему.
Публикуя его, потому что он работает, он поддерживает инкапсуляцию, и это немного менее ужасно, чем решение "Возврат-просмотр-содержащий-Javascript-перенаправление", которое я видел, но я все же хотел бы получить лучшую идею о том, как этого добиться вид упаковки более MVC.