如何在ASP.Net MVC 2中的ViewUserControl中封装form / post / validation [/ redirect]

时间:2010-05-28 03:24:41

标签: asp.net-mvc user-controls asp.net-mvc-2 viewusercontrol

简短版本:需要ViewUserControl(即登录表单)发布到自己并能够重定向(即成功登录),或返回原始视图(即主页/索引)与验证摘要,而不是干扰页面上的其他ViewUserControls。

此外,HomeController / Index应该对Login Form的内部工作知之甚少。理想情况下,只需要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或用户凭据失败时运行良好 - 返回View()确实屈服于Home / Index并显示相应的验证摘要。

(我在同一页面上有一个注册表格,使用相同的结构。每个表格的验证摘要仅显示提交该表格的时间。)

时失败:ModelState和用户凭据有效 - RedirectToAction&lt;&gt;()出现以下错误:
“不允许子操作执行重定向操作。”

似乎在经典ASP时代,这将通过Response.Buffer=True解决。现在是否有相应的设置或解决方法?

顺便说一下,运行: ASP.Net 4,MVC 2,VS 2010,开发/调试Web服务器

我希望所有这一切都有道理。

那么,我的选择是什么?或者我的方法在哪里出错了? TIA!

2 个答案:

答案 0 :(得分:0)

我会使用可以放在MasterPage / _Layout上的部分视图(例如“_Login.cshtml”或“_Login.ascx”)。在局部视图中,您可以编写一个表单标记,该标记发布到Controller上的Action(假设“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”的视图,否则将从提交表单的位置重定向。

注意:referer可能为null(例如,如果不是像fiddler这样的浏览器或脚本正在发出请求),那么就会有一些错误处理。

答案 1 :(得分:0)

古老的问题,但这基本上和我现在做的完全一样,我的搜索仍然没有发现符合所有标准的答案;我不明白为什么将登录过程完全封装起来是如此困难,但也许我只是错过了一个写得清楚的例子。

我的解决方案完美无缺,就是简单地使用旧标准

System.Web.HttpContext.Current.Response.Redirect(url, true);

...在登录过程的控制器中。

发布它因为它有效,它保持封装,并且它比我所看到的包含return-a-view-a-Javascript-redirect解决方案稍微不那么可怕,但我&#39; d还想更好地了解如何以更加MVC的方式实现这种包装。