2012-08-16 55 views
1

在我问这个问题之前,让我澄清一下,这个练习的目的是研究/概念证明,以便回答关于如何改进设计或有更简单的方法来实现这一点,虽然赞赏,可能无助于实现目标。使用Ajax在ASP .Net MVC 4中调用登录功能局部视图

我正在修改ASP .Net MVC 4应用程序的模板,以便使用ajax请求实现登录功能,该请求只更新包含控件日志的局部视图,并使页面的其余部分不受干扰。

到目前为止,我所做的是以下几点:

我已经添加的局部视图形式,以便它可以发布,并用按钮

@using (Html.BeginForm("Login", "Account", FormMethod.Post, new { ReturnUrl = ViewBag.ReturnUrl })) 
{ 
    @Html.ValidationSummary(true) 

    if (Request.IsAuthenticated) 
    { 
     <p> 
      Hello, @Html.ActionLink(User.Identity.Name, "ChangePassword", "Account", routeValues: null, htmlAttributes: new {@class = "username", title = "Change password"})! 
      @Html.ActionLink("Log off", "LogOff", "Account") 
     </p> 
    } 
    else 
    { 
     <ul> 
      <li>@Html.LabelFor(m => m.UserName)</li> 
      <li>@Html.TextBoxFor(m => m.UserName)</li> 
      <li>@Html.LabelFor(m => m.Password)</li> 
      <li>@Html.PasswordFor(m => m.Password)</li> 
      <li><input class="loginLink loginButton" type="button" value="Log in"/></li> 
      <li>@Html.ActionLink("Register", "Register", "Account", routeValues: null, htmlAttributes: new {id = "registerLink"})</li> 
     </ul> 
    } 
} 

取代操作链接我修改的动作,像这样

[AllowAnonymous] 
[HttpPost] 
public ActionResult Login(LoginModel model, string returnUrl) 
{ 
    ActionResult result = View("_LoginPartial", model); 

    if (ModelState.IsValid) 
    { 
     if (Membership.ValidateUser(model.UserName, model.Password)) 
     { 
      FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe); 
      if (Url.IsLocalUrl(returnUrl)) 
      { 
       result = Redirect(returnUrl); 
      } 
      else 
      { 
       result = View("_LoginPartial", model); 
      } 
     } 
     else 
     { 
      ModelState.AddModelError("", "The user name or password provided is incorrect."); 
     } 
    } 

    return result; 
} 

而且我创造了这个小JavaScript文件

var login = { 
    callLogin: function() { 
     var userName = $("#UserName").val(); 
     var password = $("#Password").val(); 

     var data = { UserName: userName, Password: password }; 
     $("#login").load("/Account/Login", data); 
    } 
}; 

$(document).ready(function() { 
    $(".loginButton").click(login.callLogin); 
}); 

本身的日志工作。正在调用POST操作方法并验证凭据。问题是部分视图没有被更新,我必须通过转到另一个页面强制回发,以便我可以看到部分,就好像用户登录一样。

什么是缺少的成分完成这个?

谢谢。

回答

1

两个可能的问题/解决方案:

  1. 没有与login的ID没有元素 - 确保您的形式有ID或在一个div包裹。 $("section").load("/Account/Login #login", data) - -
  2. 在调用.load传递一个选择的网址PARAM的一部分确保POST正在取得(它应该因为data是一个对象)
  3. 使用萤火虫或类似的东西,以验证检查网络流量POST正在进行,并且部分渲染正在返回。
  4. 回落到一个更手动方法:
    $.ajax("/Account/Login", { data: data, type: 'POST', dataType: 'html' }).done(function(result) { $("#login").empty().append(result); });

编辑:

我还是想知道为什么这不工作,如果我只成功登录后,退还部分视图尽管如此。

如果你仔细检查交换的HTTP头,你会发现,最初的调用来检索在200(OK),这种登录方式的局部视图结果与登录页面,而不是预期的401(未授权的无沿[AllowAnonymous] attrib)。因此,响应HTML不是您所期望的部分,而是完整的html文档。你的脚本虽然没有注意到,并且正常继续。为了解决这个问题,你需要修改你的应用程序响应未经身份验证的请求的方式。你可以做很多不同的事情,对我们来说幸运的是,菲尔·哈克回到了他们的博客。他的帖子可以找到here

+0

谢谢乔希。不幸的是,这并没有奏效。该部分封装在具有“登录”ID的

元素中。在加载方法中添加选择器不会导致任何不同。 – 2012-08-16 21:11:11

+0

更新的答案反映评论,增加了另一种方法 – 2012-08-16 21:55:45

+0

非常感谢乔希。我找到的解决方案是因为实际需要load方法中的“form”选择器,否则完整的Index视图将呈现在“section”元素中。给你一个这个投票。仍尝试了其他建议,但他们不起作用。 – 2012-08-16 22:07:26

0

ajax调用应返回需要显示的html内容,并且应用加载的元素应该是将其内容替换为ajax响应的元素。

我想我错过了什么样的加载,因为我没有使用它(赞成$ .post),但仍然应该返回一个视图(模型)。 RedirectToAction做同样的事情,因为它将重定向到一个动作,该动作将呈现该动作的视图(从而返回html内容),以便它能够工作。

+0

除了加载方法只是 - http://api.jquery.com/load/ – 2012-08-16 21:50:40

0

找到并回答它真的很酷虽然不理想。

原来,控制器需要改变一点点:

[AllowAnonymous] 
[HttpPost] 
public ActionResult Login(LoginModel model, string returnUrl) 
{ 
    ActionResult result = View("_LoginPartial", model); 

    if (ModelState.IsValid) 
    { 
     if (Membership.ValidateUser(model.UserName, model.Password)) 
     { 
      FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe); 
      if (Url.IsLocalUrl(returnUrl)) 
      { 
       result = Redirect(returnUrl); 
      } 
      else 
      { 
       //This is the only difference from the original action 
       result = RedirectToAction("Index", "Home"); 
      } 
     } 
     else 
     { 
      ModelState.AddModelError("", "The user name or password provided is incorrect."); 
     } 
    } 

    return result; 
} 

唯一的区别是,如果认证成功,我可以做RedirectToAction通话(“指数”,“家”)部分将被正确更新。

现在这是一个很酷且不理想的部分。之所以这样做,是因为即使RedirectToAction方法返回完整的Index视图,因为我现在感兴趣的部分现在有一个“form”元素,并且感谢Josh的建议,在jQuery负载中包含一个“form”选择器方法,在完整的Index视图中,只有_LoginPartial视图被加载到“login”元素中。

我认为这并不理想,因为很多不需要的HTML被返回并丢弃,这是相当大的开销。另外,如果返回的“索引”视图碰巧在其他地方具有其自己的形式,那么这两种形式将被加载到“登录”元素中,这可以通过将更具体的选择器放入加载方法。

我仍然想知道为什么这不起作用,如果我只是在尝试成功登录后才返回部分视图。

+0

看到我的更新答案的解释 – 2012-08-17 17:26:03