ajax - 使用 AJAX 和 ASP.NET Core 登录

标签 ajax asp.net-core asp.net-core-mvc

我想要登录表单作为 PartialView 或 ViewComponent。用户输入用户名和密码我想使用 ajax 登录并显示可能的验证错误,使用 jQuery 或在服务器上重新呈现登录表单。我不在乎。

这看起来微不足道,但是是否有使用 AJAX 登录的现有示例或模板?我不想重新发明轮子。

我从带有本地帐户的 ASP.NET Core Web 应用程序的默认 Visual Studio 模板开始,其中登录是单独的页面。它使用 Bootstrap 。理想情况下,我希望尽可能接近这一点。

登录后操作如下所示:

    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Login(LoginFormViewModel model, string returnUrl = null)
    {
        ViewData["ReturnUrl"] = returnUrl;
        if (ModelState.IsValid)
        {
            // This doesn't count login failures towards account lockout
            // To enable password failures to trigger account lockout, set lockoutOnFailure: true
            var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);
            if (result.Succeeded)
            {
                _logger.LogInformation(1, "User logged in.");
                return RedirectToLocal(returnUrl);
            }
            if (result.IsLockedOut)
            {
                _logger.LogWarning(2, "User account locked out.");
                return View("Lockout");
            }
            else
            {
                ModelState.AddModelError(string.Empty, "Invalid login attempt.");
            }
        }

        // If we got this far, something failed, redisplay form
        return View(model);
    }

最佳答案

这是我在帐户 Controller 中的代码片段,用于基于 AJAX 的登录,以帮助您入门:

// GET: /Account/LoginAjax
[HttpGet]
[AllowAnonymous]
[RequireHttps]
public IActionResult LoginAjax(string returnUrl = null)
{
    if (!_signInManager.IsSignedIn(User))
    {
        if (Request.Cookies["Identity.External"] != null)
        {
            // TODO: this is a temp solution, see https://github.com/aspnet/Security/pull/980
            // http://stackoverflow.com/questions/38751641/app-redirects-to-account-accessdenied-on-adding-oauth
            // when fixed in Microsoft.AspNetCore.Authentication, remove the whole block
            Response.Cookies.Delete("Identity.External");
        }
    }
    return PartialView("_LoginPartial", new LoginViewModel { RememberMe = true, ReturnUrl = returnUrl });
}

// POST: /Account/LoginAjax
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
[RequireHttps]
public async Task<IActionResult> LoginAjax(LoginViewModel model, string returnUrl = null)
{
    returnObject ret = new returnObject();
    if (ModelState.IsValid)
    {
        // This doesn't count login failures towards account lockout
        // To enable password failures to trigger account lockout, set lockoutOnFailure: true
        var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);
        if (result.Succeeded)
        {
            ret.success = true;
            ret.message = "logged-in";
        }
        else if (result.IsLockedOut)
        {
            ModelState.AddModelError(string.Empty, "This account has been locked out, please try again later.");
        }
        else
        {
            ModelState.AddModelError(string.Empty, "The email address or password supplied are incorrect. Please check your spelling and try again.");
        }
    }
    if (!ret.success)   //login was unsuccessful, return model errors
        ret.message = ModelErorrs(ModelState);

    return Json(ret);
}

public static string ModelErorrs(Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary modelState)
{
    return string.Join("; ", modelState.Values
        .SelectMany(x => x.Errors)
        .Select(x => x.ErrorMessage));
}

public class returnObject
{
    public bool success { get; set; } = false;
    public string message { get; set; } = "";
    public string action { get; set; } = "";
}

_LoginPartial.chtml:

<form id="formLoginAJAX" asp-controller="Account" asp-action="LoginAjax" asp-route-returnurl="@Model.ReturnUrl" method="post">
......
</form>

客户端 JS 原型(prototype):

// dialog form submit handler
$form.submit(function (event) {
    event.preventDefault();                
    if (!$form.valid())
        return; // form is not valid

    // submit validated form via Ajax
    var res = { success: false, message: '' };
    $.ajax({
        type: 'POST',
        dataType: 'json',
        url: $form.attr('action'),
        xhrFields: {
            withCredentials: true
        },
        data: $form.serializeObject(),
        beforeSend: function () {
            //disable submit button to prevent double-click                        
        },
        success: function (data) {
            res = data;
        },
        error: function (jqXHR, textStatus, errorThrown) {
            res.message = 'Request failed: ' + errorThrown;
        },
        complete: function () {
            if (res.success) {
                // all good, user is logged-in 
                // do callbacks if needed
                // close dialog
            } else {
                // no luck, show returned errors (res.message) in the summary (".validation-summary")                            
            }                        
        }
    });
});

关于ajax - 使用 AJAX 和 ASP.NET Core 登录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41461355/

相关文章:

jquery - 如何防止 jQuery Ajax 缓存?

javascript - 如何使用 HTTP 请求中的参数在 Django 中附加模型

asp.net-core - 通过 URL 访问 ASP.NET 5 View 组件

c# - .net 核心注入(inject)和解析服务

asp.net - 在生产服务器上运行EF迁移的最佳方法是什么?

javascript - ajax 请求中的 formdata 返回 Uncaught TypeError : Illegal invocation error

Cakephp中的Ajax分页未设置页面

c# - ILogger 不遵守 Application Insights 的日志级别

c# - 如果我向 AddControllersWithViews() 添加扩展,它是否也适用于 AddRazorPages()

visual-studio - visual studio 2015 调试器停止工作,不断收到 "error CS0103: The name does not exist in the current context "