C# 登录的部分视图不能在控制器中调用不同名称的操作方法
我正在建立一个会员唯一的ASP.NET MVC网站,该网站将为用户提供多种登录方式,用户可以使用C# 登录的部分视图不能在控制器中调用不同名称的操作方法,c#,asp.net-mvc,asp.net-mvc-4,razor,C#,Asp.net Mvc,Asp.net Mvc 4,Razor,我正在建立一个会员唯一的ASP.NET MVC网站,该网站将为用户提供多种登录方式,用户可以使用表单身份验证。因此,我们的想法是,将有一种形式用于典型的用户名和密码身份验证,然后是另一种形式用于移动电话号码的电子证书身份验证 现在我已经阅读了大量关于如何在一个视图中解决多个表单的文档,现在我有了一个相当优雅的解决方案,即一个视图包含两个包含表单的局部视图,一个视图模型包含两个模型属性。这为验证提供了一个很好的解决方案,因此在按下相应的提交按钮时,每个表单都将分别验证,而不是同时验证 代码如下:
表单身份验证
。因此,我们的想法是,将有一种形式用于典型的用户名和密码身份验证,然后是另一种形式用于移动电话号码的电子证书身份验证
现在我已经阅读了大量关于如何在一个视图中解决多个表单的文档,现在我有了一个相当优雅的解决方案,即一个视图包含两个包含表单的局部视图,一个视图模型包含两个模型属性。这为验证提供了一个很好的解决方案,因此在按下相应的提交按钮时,每个表单都将分别验证,而不是同时验证
代码如下:
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>
以下是模型:
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; }
}
然后控制器方法:
// 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
,但我不能。如果我这样命名的话,这些行动根本不会被调用。有趣的是,当我在验证后在站点的其他地方设置相同的方案时,例如在主控制器中,一切正常,我可以根据局部视图中的action name参数在控制器中调用不同的操作方法,例如,我可以:
@using (Html.BeginForm("LoginMobile", "Account", FormMethod.Post, new { @class = "form-horizontal", @role = "form", @id = "_GSMForm" }))
{
[Code omitted]
}
及
在控制器中
所以,现在,我必须让其中一个部分视图中的第一个参数名为Login,以便调用Login操作方法。控制器中只能有两个具有该名称的方法,一个用于get,一个用于post,如果我得到更多的模糊方法异常。因此,目前我面临的事实是,我必须选择是否让用户使用手机号码或用户名和密码登录,因为我无法在登录页面上同时使用这两种方法。这当然是不可接受的,当然有一种方法可以两者兼得,对吗
我希望有人知道如何解决这个难题。这与FormsAuthentication有关吗?当我最终发现是FormsAuthentication导致了这种行为时,我找到了答案
简而言之,从
web.config
中删除
节点,然后在FilterConfig.cs
addfilters.add(new AuthorizeAttribute())中删除该节点代码>很抱歉回答这么简单,请您尝试使用FormMethod。发布您的方法。因为当您尝试通过Get发送表单数据时,它可能会导致许多奇怪的问题。如果我错了,请更正。啊,我发现我在部分视图代码中犯了一个错误。第三个参数应该是FormMethod.Post。我将在我发布的控制器方法中修复该问题。我已经修复了VS中的代码,但没有任何区别。问题仍然存在。如果尝试发送LoginUserPass或LoginMobile,请从浏览器控制台添加注释。例如,如果请求以500 err结束,则它是一个点,但如果它甚至找不到控制器方法,则它是另一个点(例如,您忘记为您的操作添加allow anonymys属性,或者可能无法使用您发送的数据对模型进行反序列化。致以最诚挚的问候。您的问题不清楚。您的问题到底是什么?您现在所拥有的没有任何问题。传递“Login”的表单将调用登录
操作和传递的表单“LoginM”将调用LoginM
操作。似乎这就是您想要的,因为其他任何操作都没有意义。据我所知,当他尝试重命名Login和LoginM时,会引发问题。
// 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);
}
@using (Html.BeginForm("LoginMobile", "Account", FormMethod.Post, new { @class = "form-horizontal", @role = "form", @id = "_GSMForm" }))
{
[Code omitted]
}
public ActionResult LoginMobile(LoginMobileModel model, string returnUrl){ ... }