[英]Partial views for login can not call differently named action methods in controller
我正在構建一個成員的唯一ASP.NET MVC網站,它將為用戶提供多種使用FormsAuthentication
登錄的方法。 因此,想法是,通常的用戶名和密碼認證將采用一種形式,對於電子證書認證,將采用另一種形式作為移動電話號碼。
現在,我已經閱讀了很多有關如何在一個視圖中求解多個表單的文檔,並且現在有了一個相當優雅的解決方案,即一個視圖包含兩個包含表單的部分視圖,一個視圖包含兩個模型屬性。 這為驗證提供了一個很好的解決方案,因此在按下相應的提交按鈕時,將分別驗證每個表單,而不是同時驗證兩個表單。
這是代碼:
Login.cshtml:
@model OneMeetingPortal2.Models.ViewModel
@{
ViewBag.Title = "Login";
}
<div class="container">
<div class="well">
<h1>@ViewBag.Title.</h1>
</div>
@Html.Partial("_LoginUsernamePasswordPartial", Model.UserPass)
@Html.Partial("_LoginMobilePartial", Model.Mobile)
</div>
_LoginUsernamePasswordPartial.cshtml:
@model OneMeetingPortal2.Models.LoginUsernamePasswordModel
@using (Html.BeginForm("Login", "Account", FormMethod.Post, new { @class = "form-horizontal", @role = "form", @id = "_userNameForm" }))
{
@Html.AntiForgeryToken()
//Birtingu validation elements er stjórnað með CSS. Sjá .validation-summary-valid í Main.css. Birtist ef villa kemur fram.
@Html.ValidationSummary("Eftirfarandi villur komu upp:", new { @class = "alert alert-danger col-sm-offset-2 col-sm-10" })
<div class="form-group">
@Html.LabelFor(m => m.UserName, new { @class = "control-label col-sm-2" })
<div class="col-sm-10">
@Html.TextBoxFor(m => m.UserName, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.UserName)
</div>
</div>
<div class="form-group">
@Html.LabelFor(m => m.Password, new { @class = "control-label col-sm-2" })
<div class="col-sm-10">
@Html.PasswordFor(m => m.Password, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.Password)
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<input type="submit" value="Log in" class="btn btn-default" />
</div>
</div>
}
_LoginMobilePartial.cshtml。 請注意,如果將操作名稱參數更改為“ Login
,則會收到有關模棱兩可的操作名稱的錯誤消息:
@model OneMeetingPortal2.Models.LoginMobileModel
@using (Html.BeginForm("LoginM", "Account", FormMethod.Post, new { @class = "form-horizontal", @role = "form", @id = "_GSMForm" }))
{
@Html.AntiForgeryToken()
@Html.ValidationSummary("Eftirfarandi villur komu upp:", new { @class= "alert alert-danger col-sm-offset-2 col-sm-10" })
<div class="form-group">
@Html.LabelFor(m => m.MobileNumber, new { @class = "control-label col-sm-2" })
<div class="col-sm-10">
@Html.TextBoxFor(m => m.MobileNumber, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.MobileNumber)
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<input type="submit" value="Log in" class="btn btn-default" />
</div>
</div>
}
這是模型:
public class ViewModel
{
public LoginMobileModel Mobile { get; set; }
public LoginUsernamePasswordModel UserPass { get; set; }
}
public class LoginUsernamePasswordModel
{
[Required(ErrorMessage="Ekki má sleppa notandanafni.")]
[Display(Name = "Notandanafn")]
[StringLength(50, ErrorMessage = "Notandanafnið má ekki vera lengra en 50 stafir")]
[MinLength(3, ErrorMessage = "Notandanafnið verður að vera a.m.k. 3 stafir")]
public string UserName { get; set; }
[Required(ErrorMessage="Ekki má sleppa lykilorði.")]
[DataType(DataType.Password)]
[Display(Name = "Lykilorð")]
[StringLength(50, ErrorMessage="Lykilorðið má ekki vera lengra en 50 stafir")]
[MinLength(3, ErrorMessage="Lykilorðið verður að vera a.m.k. 3 stafir")]
public string Password { get; set; }
}
public class LoginMobileModel
{
[Required(ErrorMessage = "Ekki má sleppa símanúmeri.")]
[Display(Name = "Farsímanúmer")]
[StringLength(7, ErrorMessage = "Símanúmer má ekki vera lengra en 7 stafir.")]
[MinLength(7, ErrorMessage = "Símanúmer má ekki vera styttra en 7 stafir.")]
public string MobileNumber { get; set; }
}
然后是Controller方法:
// GET: /Account/Login
[HttpGet]
[AllowAnonymous]
public ActionResult Login(string returnUrl)
{
ViewBag.ReturnUrl = returnUrl;
ViewModel m = new ViewModel();
m.Mobile = new LoginMobileModel();
m.UserPass = new LoginUsernamePasswordModel();
return View(m);
}
//
// POST: /Account/Login
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginUsernamePasswordModel model, string returnUrl)
{
if (ModelState.IsValid)
{
if (_accountService.Login(model.UserName, model.Password))
{
string xmlString = _accountService.GetEmployeeDetails(model.UserName);
Session.Add("ProfileXml", xmlString);
Classes.Profile profile = new Classes.Profile(xmlString);
FormsAuthentication.RedirectFromLoginPage(profile.Subject, false);
}
}
// If we got this far, something failed, redisplay form
ViewModel m = new ViewModel();
m.UserPass = model;
m.Mobile = new LoginMobileModel();
return View(m);
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult LoginM(LoginMobileModel model, string returnUrl)
{
if (ModelState.IsValid)
{
MobileLoginReturn mlr = _accountService.LoginGSM(model.MobileNumber);
if(mlr.Error == null)
{
Session.Add("ProfileXml", mlr.EmployeeXmlString);
Classes.Profile profile = new Classes.Profile(mlr.EmployeeXmlString);
FormsAuthentication.RedirectFromLoginPage(profile.Subject, false);
}
else
{
ModelState.AddModelError("", mlr.Error.Message);
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
但是,我得到一個奇怪的行為,該行為似乎僅與登錄頁面有關。 我想有兩種不同的操作方法,分別稱為LoginUserPass
和LoginMobile
但我不能。 如果我這樣命名,這些動作將不會被調用。 有趣的是,當我在身份驗證后在站點的其他地方設置相同的方案時,例如在Home控制器中,一切正常,並且我可以基於部分視圖中的action name參數在控制器中調用不同的action方法,例如,我可以有:
@using (Html.BeginForm("LoginMobile", "Account", FormMethod.Post, new { @class = "form-horizontal", @role = "form", @id = "_GSMForm" }))
{
[Code omitted]
}
和
public ActionResult LoginMobile(LoginMobileModel model, string returnUrl){ ... }
在控制器中。
因此,現在,我必須讓部分視圖之一中的第一個參數名稱為Login,這樣才能調用Login操作方法。 控制器中只能有兩種具有該名稱的方法,一種用於get,一種用於post,如果更多,我將得到模棱兩可的方法異常。 因此,目前我面臨這樣一個事實,我必須選擇是否要讓用戶使用手機號碼或用戶名和密碼登錄,因為我無法在登錄頁面上同時使用這兩種方法。 那當然是不可接受的,肯定有辦法兩者兼而有之吧?
我希望有人知道如何解決這個難題。 這與FormsAuthentication有關系嗎?
當我最終弄清楚是FormsAuthentication導致了此行為時,我在這里找到了答案
簡而言之,從web.config
刪除<authorization>
節點,然后在FilterConfig.cs
添加filters.Add(new AuthorizeAttribute());
FilterConfig.cs
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.