2012-08-16 71 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