diff --git a/src/BootstrapBlazor.Server/Controllers/Api/UserController.cs b/src/BootstrapBlazor.Server/Controllers/Api/UserController.cs
new file mode 100644
index 0000000000000000000000000000000000000000..a1e051317fa428801178dbcdde907b0d4c53e60d
--- /dev/null
+++ b/src/BootstrapBlazor.Server/Controllers/Api/UserController.cs
@@ -0,0 +1,25 @@
+// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+// Website: https://www.blazor.zone or https://argozhang.github.io/
+
+using BootstrapBlazor.Shared;
+using Microsoft.AspNetCore.Authentication;
+using Microsoft.AspNetCore.Mvc;
+
+namespace BootstrapBlazor.Server.Controllers.Api;
+
+[Route("api/[controller]/[action]")]
+[ApiController]
+public class UserController : ControllerBase
+{
+ [HttpPost]
+ public IActionResult Login(User user)
+ {
+ if (user.UserName == "admin" && user.Password == "123456")
+ {
+ return new JsonResult( new { Code = 200, Message = "登录成功" });
+ }
+
+ return new JsonResult(new { Code = 500, Message = "用户名或密码错误" });
+ }
+}
diff --git a/src/BootstrapBlazor.Shared/Data/User.cs b/src/BootstrapBlazor.Shared/Data/User.cs
new file mode 100644
index 0000000000000000000000000000000000000000..cd4ff25359ef2177ba70aef25b86bc9894cce4c6
--- /dev/null
+++ b/src/BootstrapBlazor.Shared/Data/User.cs
@@ -0,0 +1,21 @@
+// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+// Website: https://www.blazor.zone or https://argozhang.github.io/
+
+namespace BootstrapBlazor.Shared;
+
+///
+/// 登录模拟类
+///
+public class User
+{
+ ///
+ /// 用户名
+ ///
+ public string? UserName { get; set; }
+
+ ///
+ /// 密码
+ ///
+ public string? Password { get; set; }
+}
diff --git a/src/BootstrapBlazor.Shared/Samples/Ajaxs.razor b/src/BootstrapBlazor.Shared/Samples/Ajaxs.razor
new file mode 100644
index 0000000000000000000000000000000000000000..4c917a5a6d6ac89738006acf1f6a84b4170ec724
--- /dev/null
+++ b/src/BootstrapBlazor.Shared/Samples/Ajaxs.razor
@@ -0,0 +1,19 @@
+@page "/ajaxs"
+
+
Ajax调用
+
+用于直接在浏览器使用js的ajax方法与服务器交互.目前只支持输入输出皆为json,返回值为json字符串,可以自行转换处理。
+
+
+
+
+
+ 特别注意:
+
+ 这里只是进行了登录模拟,并没有真正的调用HttpContext.SignIn,真实使用时需要在登录完成后对页面进行刷新,否则无法真正的登录成功。
+
+
+ @ResultMessage
+
+
+
diff --git a/src/BootstrapBlazor.Shared/Samples/Ajaxs.razor.cs b/src/BootstrapBlazor.Shared/Samples/Ajaxs.razor.cs
new file mode 100644
index 0000000000000000000000000000000000000000..72ea8348d63b73255a9ab3285a286c7004b66a87
--- /dev/null
+++ b/src/BootstrapBlazor.Shared/Samples/Ajaxs.razor.cs
@@ -0,0 +1,77 @@
+// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+// Website: https://www.blazor.zone or https://argozhang.github.io/
+
+using BootstrapBlazor.Components;
+using Microsoft.AspNetCore.Components;
+using System.Diagnostics.CodeAnalysis;
+using System.Text.Json;
+using System.Threading.Tasks;
+
+namespace BootstrapBlazor.Shared.Samples;
+
+///
+/// Ajax示例类
+///
+public partial class Ajaxs
+{
+ private string? ResultMessage { get; set; }
+
+ [Inject]
+ [NotNull]
+ private AjaxService? AjaxService { get; set; }
+
+ [Inject]
+ [NotNull]
+ private SwalService? SwalService { get; set; }
+
+ private async Task Success()
+ {
+ AjaxOption option = new AjaxOption();
+ option.Url = "/api/User/Login";
+ option.Data = new User() { UserName = "admin", Password = "123456" };
+ var result = await AjaxService.GetMessage(option);
+ if (result == null)
+ {
+ ResultMessage = "响应失败";
+ }
+ else
+ {
+ ResultMessage = result;
+ var doc = JsonDocument.Parse(result);
+ if (200 == doc.RootElement.GetProperty("code").GetInt32())
+ {
+ await SwalService.Show(new SwalOption() { Content = "登录成功!", Category = SwalCategory.Success });
+ }
+ else
+ {
+ await SwalService.Show(new SwalOption() { Content = $"登录失败:{doc.RootElement.GetProperty("message").GetString()}", Category = SwalCategory.Error });
+ }
+ }
+ }
+
+ private async Task Fail()
+ {
+ AjaxOption option = new AjaxOption();
+ option.Url = "/api/User/Login";
+ option.Data = new User() { UserName = "admin", Password = "1234567" };
+ var result = await AjaxService.GetMessage(option);
+ if (result == null)
+ {
+ ResultMessage = "响应失败";
+ }
+ else
+ {
+ ResultMessage = result;
+ var doc = JsonDocument.Parse(result);
+ if (200 == doc.RootElement.GetProperty("code").GetInt32())
+ {
+ await SwalService.Show(new SwalOption() { Content = "登录成功!", Category = SwalCategory.Success });
+ }
+ else
+ {
+ await SwalService.Show(new SwalOption() { Content = $"登录失败:{doc.RootElement.GetProperty("message").GetString()}", Category = SwalCategory.Error });
+ }
+ }
+ }
+}
diff --git a/src/BootstrapBlazor.Shared/Shared/NavMenu.razor.cs b/src/BootstrapBlazor.Shared/Shared/NavMenu.razor.cs
index c2bc447e23b3233843913b99b4dc04723579100b..c12b27d37397021c62394d2b1600c36ab7d4bbb8 100644
--- a/src/BootstrapBlazor.Shared/Shared/NavMenu.razor.cs
+++ b/src/BootstrapBlazor.Shared/Shared/NavMenu.razor.cs
@@ -15,7 +15,7 @@ using System.Threading.Tasks;
namespace BootstrapBlazor.Shared.Shared;
///
-///
+///
///
public sealed partial class NavMenu
{
@@ -523,6 +523,11 @@ public sealed partial class NavMenu
Text = Localizer["Transition"],
Url = "transitions"
},
+ new()
+ {
+ Text = "Ajax",
+ Url = "ajaxs"
+ },
};
AddBadge(item);
}
diff --git a/src/BootstrapBlazor/Components/Ajax/Ajax.cs b/src/BootstrapBlazor/Components/Ajax/Ajax.cs
new file mode 100644
index 0000000000000000000000000000000000000000..bccdcf0b27600db70913f8571cdb9b391575faae
--- /dev/null
+++ b/src/BootstrapBlazor/Components/Ajax/Ajax.cs
@@ -0,0 +1,56 @@
+// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+// Website: https://www.blazor.zone or https://argozhang.github.io/
+
+using Microsoft.AspNetCore.Components;
+using Microsoft.JSInterop;
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Threading.Tasks;
+
+namespace BootstrapBlazor.Components;
+
+///
+/// Ajax组件
+///
+public class Ajax : BootstrapComponentBase, IDisposable
+{
+ [Inject]
+ [NotNull]
+ private AjaxService? AjaxService { get; set; }
+
+ ///
+ /// OnInitialized 方法
+ ///
+ protected override void OnInitialized()
+ {
+ base.OnInitialized();
+ AjaxService.Register(this, GetMessage);
+ }
+
+ private async Task GetMessage(AjaxOption option)
+ {
+ var obj = await JSRuntime.InvokeAsync(identifier: "$.bb_ajax", option.Url, option.Method, option.Data);
+ return obj;
+ }
+
+ ///
+ /// Dispose 方法
+ ///
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ AjaxService.UnRegister(this);
+ }
+ }
+
+ ///
+ /// Dispose 方法
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+}
diff --git a/src/BootstrapBlazor/Components/Ajax/Ajax.js b/src/BootstrapBlazor/Components/Ajax/Ajax.js
new file mode 100644
index 0000000000000000000000000000000000000000..32914e219e576325ef5fc4f39227401186c829a4
--- /dev/null
+++ b/src/BootstrapBlazor/Components/Ajax/Ajax.js
@@ -0,0 +1,23 @@
+(function ($) {
+ $.extend({
+ bb_ajax: function (url, method, data) {
+ data = JSON.stringify(data)
+ var res = null
+ $.ajax({
+ url: url,
+ data: data,
+ method: method,
+ contentType: 'application/json',
+ dataType: 'json',
+ async: false,
+ success: function (result) {
+ res = result
+ },
+ error: function (XMLHttpRequest, textStatus, errorThrown) {
+ return null
+ }
+ })
+ return JSON.stringify(res)
+ }
+ });
+})(jQuery);
diff --git a/src/BootstrapBlazor/Components/Ajax/AjaxOption.cs b/src/BootstrapBlazor/Components/Ajax/AjaxOption.cs
new file mode 100644
index 0000000000000000000000000000000000000000..b5d048c8cde5de5bf5059f8dbab57de94ecca551
--- /dev/null
+++ b/src/BootstrapBlazor/Components/Ajax/AjaxOption.cs
@@ -0,0 +1,31 @@
+// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+// Website: https://www.blazor.zone or https://argozhang.github.io/
+
+using System.Diagnostics.CodeAnalysis;
+
+namespace BootstrapBlazor.Components;
+
+///
+/// Ajax配置类
+///
+public class AjaxOption
+{
+ ///
+ /// 获取/设置 要上传的参数类
+ ///
+ [NotNull]
+ public object? Data { get; set; }
+
+ ///
+ /// 获取/设置 传输方式,默认为POST
+ ///
+ public string Method { get; set; } = "POST";
+
+ ///
+ /// 获取/设置 请求的URL
+ ///
+ [NotNull]
+ public string? Url { get; set; }
+
+}
diff --git a/src/BootstrapBlazor/Components/Ajax/AjaxService.cs b/src/BootstrapBlazor/Components/Ajax/AjaxService.cs
new file mode 100644
index 0000000000000000000000000000000000000000..1ef134869408eb03a86aeee32df7300c6abd3389
--- /dev/null
+++ b/src/BootstrapBlazor/Components/Ajax/AjaxService.cs
@@ -0,0 +1,52 @@
+// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+// Website: https://www.blazor.zone or https://argozhang.github.io/
+
+using Microsoft.AspNetCore.Components;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace BootstrapBlazor.Components;
+
+///
+/// Ajax服务类
+///
+public class AjaxService
+{
+ ///
+ /// 获得 回调委托缓存集合
+ ///
+ private List<(IComponent Key, Func> Callback)> Cache { get; set; } = new();
+
+ ///
+ /// 注册服务
+ ///
+ ///
+ ///
+ internal void Register(IComponent key, Func> callback) => Cache.Add((key, callback));
+
+ ///
+ /// 注销事件
+ ///
+ internal void UnRegister(IComponent key)
+ {
+ var item = Cache.FirstOrDefault(i => i.Key == key);
+ if (item.Key != null)
+ {
+ Cache.Remove(item);
+ }
+ }
+
+ ///
+ /// 调用Ajax方法发送请求
+ ///
+ ///
+ ///
+ public async Task GetMessage(AjaxOption option)
+ {
+ var cb = Cache.FirstOrDefault().Callback;
+ return cb == null ? null : await cb.Invoke(option);
+ }
+}
diff --git a/src/BootstrapBlazor/Extensions/BootstrapBlazorServiceCollectionExtensions.cs b/src/BootstrapBlazor/Extensions/BootstrapBlazorServiceCollectionExtensions.cs
index 626f14347a83c0ba9d07745ea7081bf4c2a1625f..43ecb957b8a3e6046a54bd1d56c1c1c8745210cb 100644
--- a/src/BootstrapBlazor/Extensions/BootstrapBlazorServiceCollectionExtensions.cs
+++ b/src/BootstrapBlazor/Extensions/BootstrapBlazorServiceCollectionExtensions.cs
@@ -49,6 +49,7 @@ public static class BootstrapBlazorServiceCollectionExtensions
services.TryAddScoped();
services.TryAddScoped();
services.TryAddScoped();
+ services.TryAddScoped();
services.TryAddSingleton, ConfigureOptions>();
services.Configure(options =>