2015-09-07 76 views
1

我有一個使用內置表單身份驗證(與MDF數據庫存儲在App_data中)的MVC項目。我想將登錄表單更改爲Ajax登錄表單,以便我可以利用「onSuccess」和「onFailure」選項。Ajax從MVC登錄

有沒有人有我如何實現這個工作的例子,因爲我已經嘗試過previuosly,但我無法獲得表單來驗證它只是無所事事。我想我可能錯過了一步,所以任何幫助表示讚賞。

示例代碼也是人造的。請在下面找到我目前的代碼。

登錄視圖

@model MyProject.Models.LoginViewModel 

@using (Ajax.BeginForm("Login", "Account", null, new AjaxOptions 
    { 
     OnSuccess = "OnSuccess", 
     OnBegin = "OnBegin", 
     OnFailure = "OnFailure", 
     OnComplete = "OnComplete", 
     HttpMethod = "POST", 
     UpdateTargetId = "target" 
    })) 
    { 
     @Html.AntiForgeryToken() 
     @Html.ValidationSummary(true) 
     <fieldset> 
      <legend>Login Form</legend> 
      <ol> 
       <li> 
       @Html.LabelFor(m => m.UserName) 
       @Html.TextBoxFor(m => m.UserName) 
       @Html.ValidationMessageFor(m => m.UserName) 
       </li> 
       <li> 
       @Html.LabelFor(m => m.Password) 
       @Html.PasswordFor(m => m.Password) 
       @Html.ValidationMessageFor(m => m.Password) 
       </li> 
       <li> 
       @Html.CheckBoxFor(m => m.RememberMe) 
       @Html.LabelFor(m => m.RememberMe, new { @class = "checkbox" }) 
       </li> 
      </ol> 
      <input type="submit" value="Login" /> 
      </fieldset> 
} 

這裏是登錄控制器

[HttpPost] 
    [AllowAnonymous] 
    [ValidateAntiForgeryToken] 
    public JsonResult ValidateUser(string userid, string password, 
            bool rememberme) 
    { 
     LoginStatus status = new LoginStatus(); 
     if (Membership.ValidateUser(userid, password)) 
     { 
      FormsAuthentication.SetAuthCookie(userid, rememberme); 
      status.Success = true; 
      status.TargetURL = FormsAuthentication. 
           GetRedirectUrl(userid, rememberme); 
      if (string.IsNullOrEmpty(status.TargetURL)) 
      { 
       status.TargetURL = FormsAuthentication.DefaultUrl; 
      } 
      status.Message = "Login attempt successful!"; 
     } 
     else 
     { 
      status.Success = false; 
      status.Message = "Invalid UserID or Password!"; 
      status.TargetURL = FormsAuthentication.LoginUrl; 
     } 
     return Json(status); 
    } 

在這裏被用於處理形式

在網頁上的登錄視圖模型

public class LoginStatus 
{ 
    public bool Success { get; set; } 
    public string Message { get; set; } 
    public string TargetURL { get; set; } 
} 

腳本

$(document).ready(function() { 
    $("#login").click(function() { 

     $("#message").html("Logging in..."); 

     var data = { 
      "UserName": $("#userid").val(), 
      "Password": $("#password").val(), 
      "RememberMe": $("#rememberme").prop("checked") 
      }; 
     $.ajax({ 
      url: "/Home/Index", 
      type: "POST", 
      data: JSON.stringify(data), 
      dataType: "json", 
      contentType: "application/json", 
      success: function (status) { 
       $("#message").html(status.Message); 
       if (status.Success) 
       { 
        window.location.href = status.TargetURL; 
       } 
      }, 
      error: function() { 
       $("#message").html("Error while authenticating user credentials!"); 
      } 
     }); 
    }); 
}); 
+0

可以顯示(OnSuccess)函數的代碼嗎? – Ala

+0

我已將它添加到最後的阿拉 – Yanayaya

回答

0

我有一個擴展名(MvcNotification)放入ViewData或TempData消息顯示。

爲了補充這一點,我的帖子操作返回「ERROR」或「OK」,我在ajax窗體OnSuccess中使用這些消息。

消息類型

public enum MessageType 
{ 
    Success, 
    Warning, 
    Error, 
    Info  
} 

AjaxMessagesFilter

/// <summary> 
/// If we're dealing with ajax requests, any message that is in the view  data goes to the http header. 
/// </summary> 
public class AjaxMessagesFilter : ActionFilterAttribute 
{ 
    public override void OnActionExecuted(ActionExecutedContext filterContext) 
    { 
     if (filterContext.HttpContext.Request.IsAjaxRequest()) 
     { 
      var viewData = filterContext.Controller.ViewData; 
      var response = filterContext.HttpContext.Response; 

      foreach (var messageType in Enum.GetNames(typeof(MessageType))) 
      { 
       var message = viewData.ContainsKey(messageType) 
          ? viewData[messageType] 
          : null; 
       if (message != null) // We store only one message in the http header. First message that comes wins. 
       { 
        response.AddHeader("X-Message-Type", messageType.ToLower()); 
        response.AddHeader("X-Message", HttpUtility.HtmlEncode(message.ToString())); 
        return; 
       } 
      } 
     } 
    } 
} 

ControllerExtensions

public static class ControllerExtensions 
{ 
    public static ActionResult ShowMessage(this Controller controller, MessageType messageType, string message, bool showAfterRedirect = false, bool UseJson = false) 
    { 
     var messageTypeKey = messageType.ToString(); 
     if (showAfterRedirect) 
     { 
      controller.TempData[messageTypeKey] = message; 
     } 
     else 
     { 
      controller.ViewData[messageTypeKey] = message; 
     } 

     if (UseJson) 
      return new JsonResult() { Data = "ERROR", JsonRequestBehavior = JsonRequestBehavior.AllowGet }; 
     else 
      return new ContentResult() { Content = "ERROR" }; 
    } 

    public static ActionResult ShowMessage(this ControllerBase controller, MessageType messageType, string message, bool showAfterRedirect = false, bool UseJson = false) 
    { 
     var messageTypeKey = messageType.ToString(); 
     if (showAfterRedirect) 
     { 
      controller.TempData[messageTypeKey] = message; 
     } 
     else 
     { 
      controller.ViewData[messageTypeKey] = message; 
     } 

     if (UseJson) 
      return new JsonResult() { Data = "ERROR", JsonRequestBehavior = JsonRequestBehavior.AllowGet }; 
     else 
      return new ContentResult() { Content = "ERROR" }; 
    } 

    public static ActionResult EmptyField(this Controller controller, string FieldName, bool IsJson = false) 
    { 
     controller.ShowMessage(MessageType.Info, String.Format("O campo \"{0}\" é de carácter obrigatório.", FieldName)); 
     return IsJson == false ? (ActionResult)new ContentResult() { Content = "ERROR" } : (ActionResult)new JsonResult() { Data = "ERROR", JsonRequestBehavior = JsonRequestBehavior.AllowGet }; 
    } 
} 

呼叫分機控制器內部:

this.ShowMessage(MessageType.Error, "An error has occurred"); 
如果你想在消息被拋出後重定向

,您需要在最後一個參數添加真。

this.ShowMessage(MessageType.Error, "An error has occurred", true); 

注:我創建了EmptyField方法給一個非標準的消息時,有些字段爲空。

操作示例(LoginPost)

[HttpPost] 
[AllowAnonymous] 
public ActionResult LoginPost(LoginViewModel model, string returnUrl, bool Relogin = false) 
{ 
    returnUrl = string.IsNullOrEmpty(returnUrl) || string.IsNullOrWhiteSpace(returnUrl) ? "/" : returnUrl; 

    if (string.IsNullOrEmpty(model.UserName)) 
     return this.EmptyField(Resource_General.UserName); 

    if (string.IsNullOrEmpty(model.Password)) 
     return this.EmptyField(Resource_General.Password); 

    // This doesn't count login failures towards account lockout 
    // To enable password failures to trigger account lockout, change to shouldLockout: true 
    var result = SignInManager.PasswordSignIn(model.UserName, model.Password, model.RememberMe, shouldLockout: false); 

    switch (result) 
    { 
     case SignInStatus.Success: 
      var user = db.Users.FirstOrDefault(x => x.UserName == model.UserName); 

      if (!user.IsActive) 
      { 
       AuthenticationManager.SignOut(); 
       this.ShowMessage(MessageType.Error, Messages.LockedOutUser); 
       return Content("ERROR"); 
      } 

      if (Url.IsLocalUrl(returnUrl)) 
       return Content(returnUrl); 
      else 
       return Content("/Home"); 
     case SignInStatus.LockedOut: 
      this.ShowMessage(MessageType.Error, Messages.LockedOutUser); 
      return Content("ERROR"); 
     case SignInStatus.RequiresVerification: 
     case SignInStatus.Failure: 
     default: 
      this.ShowMessage(MessageType.Error, Messages.WrongPassword); 
      return Content("ERROR"); 
    } 
} 

Ajax的表格

@using (Ajax.BeginForm("LoginPost", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, new AjaxOptions { OnSuccess = "OnSuccess" }, new { @id = "login-form" })) 
{ 
    @Html.AntiForgeryToken() 

    <div class="network-login-fields"> 
     <div class="form-group"> 
      <div class="input-group col-xs-12"> 
       @Html.TextBoxFor(m => m.UserName, new { @class = "form-control", placeholder = Resource_General.UserNamePlaceHolder, name = "loginname", autofocus = "true" }) 
      </div> 
     </div> 

     <div class="form-group"> 
      <div class="input-group col-xs-12"> 
       @Html.PasswordFor(m => m.Password, new { @class = "form-control", placeholder = Resource_General.PasswordPlaceHolder, name = "password" }) 

      </div> 
     </div> 

     <div class="network-login-links"> 
      <button class="btn btn-default"><i class="fa fa-sign-in"></i>&nbsp;@Resource_General.Login</button> 
     </div> 
    </div> 
} 

的Javascript

function OnSuccess(data) { 
    if (data != "ERROR") { 
     window.location.href = data; 
    } 
} 

在JavaScript中,您需要處理ajax表單OnSuccess,並在響應爲「OK」或「ERROR」時執行某些操作。

在你的主JavaScript文件,你需要有這樣的:

處理消息

// START Messages and Notifications 
function handleAjaxMessages() { 
    $(document).ajaxStart(function() { 
     Openloading(); 
    }).ajaxComplete(function (e, xhr, settings) { 
     CloseLoading(); 
    }).ajaxSuccess(function (event, request) { 
     checkAndHandleMessageFromHeader(request); 
    }).ajaxError(function (event, jqXHR, ajaxSettings, thrownError) { 
     if (thrownError !== "abort") { 
      CloseLoading(); 
      NotifyError(); 
     } 
     OnInit(); 
    }); 
} 

function checkAndHandleMessageFromHeader(request) { 
    var msg = request.getResponseHeader('X-Message'); 
    if (msg) { 
     var title = NotifyHeader(request.getResponseHeader('X-Message-Type')); 
     Notify(msg, title, request.getResponseHeader('X-Message-Type')); 
    } 
} 

function NotifyHeader(type) { 
    console.log(type); 
    var title = ""; 
    if (type == "error") 
     title = CustomScriptsLocales.ErrorTitle; 
    if (type == "success") 
     title = CustomScriptsLocales.SuccessTitle; 
    if (type == "warning") 
     title = CustomScriptsLocales.WarningTitle; 
    if (type == "info") 
     title = CustomScriptsLocales.InfoTitle; 
    console.log(title); 
    return title; 
} 

function Notify(message, title, type) { 
    if (title == null || title == "" || title == undefined) { 
     title = NotifyHeader(type); 
    } 

    PNotify.desktop.permission(); 
    var notice = new PNotify({ 
     title: title, 
     text: decodeHtml(message), 
     nonblock: { 
      nonblock: true, 
      nonblock_opacity: .55 
     }, 
     buttons: { 
      closer: true, 
     }, 
     desktop: { 
      desktop: false, 
     }, 
     hide: true, 
     type: type, 
     delay: 2000, 
     insert_brs: true, 
     remove: true, 
    }); 
} 

function NotifyError() { 
    Notify(CustomScriptsLocales.ErrorMessage, CustomScriptsLocales.ErrorTitle, "error"); 
} 
// END Messages and Notifications 

,並稱之爲一個現成的函數內部:

$(document).ready(function() { 
    handleAjaxMessages(); 
} 

注:我使用PNotify插件顯示通知。如果你不想通知只是排除所有這些JavaScript「處理消息」。