Repository: ant-design-blazor/ant-design-blazor (csharp)

Issue:
After updating to version 0.19.5.1, the OnFeedbackOkAsync method in the Modal cannot be called.
 0.19.5.1 After updating, the ModalService.CreateConfirmAsync method was used to create a dialog box.

In the component that inherits from FeedbackComponent,
public override async Task OnFeedbackOkAsync(ModalClosingEventArgs args)

The OK button click event does not trigger this method as expected. This issue might be resolved in version 0.19.4, behaving as intended.

Pull request:
<!--
First of all, thank you for your contribution! 😄

New feature please send pull request to feature branch, and rest to master branch.
Pull request will be merged after one of collaborators approve.
Please makes sure that these form are filled before submitting your pull request, thank you!

[[中文版模板 / Chinese template](https://github.com/ant-design-blazor/ant-design-blazor/blob/master/.github/PULL_REQUEST_TEMPLATE/pr_cn.md)]

-->

### 🤔 This is a ...

- [ ] New feature
- [x] Bug fix
- [ ] Site / documentation update
- [ ] Demo update
- [ ] Component style update
- [ ] Bundle size optimization
- [ ] Performance optimization
- [ ] Refactoring
- [ ] Code style optimization
- [ ] Test Case
- [ ] Branch merge
- [ ] Other (about what?)

### 🔗 Related issue link

<!--
1. Describe the source of requirement, like related issue link.
-->

### 💡 Background and solution

<!--
1. Describe the problem and the scenario.
2. GIF or snapshot should be provided if includes UI/interactive modification.
3. How to fix the problem, and list final API implementation and usage sample if that is an new feature.
-->

### 📝 Changelog

<!--
Describe changes from userside, and list all potential break changes or other risks.
--->

| Language   | Changelog |
| ---------- | --------- |
| 🇺🇸 English |           |
| 🇨🇳 Chinese |           |

### ☑️ Self Check before Merge

⚠️ Please check all items below before review. ⚠️

- [ ] Doc is updated/provided or not needed
- [ ] Demo is updated/provided or not needed
- [ ] Changelog is provided or not needed

Patch:
diff --git a/components/modal/config/DialogOptions.cs b/components/modal/config/DialogOptions.cs
index 94a4a30a8c..73e41707b4 100644
--- a/components/modal/config/DialogOptions.cs
+++ b/components/modal/config/DialogOptions.cs
@@ -15,7 +15,9 @@ public class DialogOptions : DialogOptionsBase
         /// <summary>
         /// trigger after Dialog is closed
         /// </summary>
-        public Func<Task> OnClosed { get; set; }
+        public Func<Task> AfterClose { get; set; } = () => Task.CompletedTask;
+
+        public Func<Task> AfterOpen { get; set; } = () => Task.CompletedTask;
 
         /// <summary>
         /// ant-modal-body style
@@ -45,7 +47,26 @@ public class DialogOptions : DialogOptionsBase
         /// <summary>
         /// Whether to apply loading visual effect for OK button or not
         /// </summary>
-        public bool ConfirmLoading { get; set; }
+        public bool ConfirmLoading
+        {
+            get
+            {
+                if (OkButtonProps != null)
+                {
+                    return OkButtonProps.Loading;
+                }
+                return false;
+            }
+            set
+            {
+                if (OkButtonProps == null)
+                {
+                    OkButtonProps = new ButtonProps();
+                }
+
+                OkButtonProps.Loading = value;
+            }
+        }
 
         /// <summary>
         /// modal header
@@ -65,7 +86,7 @@ public class DialogOptions : DialogOptionsBase
         /// <summary>
         /// ChildContent
         /// </summary>
-        public RenderFragment ChildContent { get; set; }
+        public RenderFragment Content { get; set; }
 
         /// <summary>
         /// the class name of the element of ".ant-modal"
@@ -76,13 +97,13 @@ public class DialogOptions : DialogOptionsBase
         /// for OK-Cancel Confirm dialog, cancel button clicked callback.
         /// It's only trigger in Confirm created by ModalService mode
         /// </summary>
-        public Func<MouseEventArgs, Task> OnCancel { get; set; }
+        public virtual Func<MouseEventArgs, Task> OnCancel { get; set; }
 
         /// <summary>
         /// for OK-Cancel Confirm dialog, OK button clicked callback.
         /// It's only trigger in Confirm created by ModalService mode
         /// </summary>
-        public Func<MouseEventArgs, Task> OnOk { get; set; }
+        public virtual Func<MouseEventArgs, Task> OnOk { get; set; }
 
         /// <summary>
         /// max modal body content height
diff --git a/components/modal/config/ModalOptions.cs b/components/modal/config/ModalOptions.cs
index 5b99045a0a..d100cafe5f 100644
--- a/components/modal/config/ModalOptions.cs
+++ b/components/modal/config/ModalOptions.cs
@@ -9,148 +9,46 @@ namespace AntDesign
     /// <summary>
     /// The options of Modal dialog box
     /// </summary>
-    public class ModalOptions : DialogOptionsBase
+    public class ModalOptions : DialogOptions
     {
-        public ModalOptions()
-        {
-            _onCancel = DefaultOnCancelOrOk;
-            _onOk = DefaultOnCancelOrOk;
-            Width = 520;
-            MaskClosable = true;
-        }
+        private Func<MouseEventArgs, Task> _onCancel;
+        private Func<MouseEventArgs, Task> _onOk;
 
         internal ModalRef ModalRef { get; set; }
 
-        /// <summary>
-        /// trigger after Dialog is closed
-        /// </summary>
-        public Func<Task> AfterClose { get; set; } = () => Task.CompletedTask;
-
         /// <summary>
         /// ant-modal style
         /// </summary>
         public string Style { get; set; }
 
-        /// <summary>
-        /// ant-modal-body style
-        /// </summary>
-        public string BodyStyle { get; set; }
-
-        /// <summary>
-        /// show ant-modal-closer 
-        /// </summary>
-        public bool Closable { get; set; } = true;
-
-        /// <summary>
-        /// Draggable modal
-        /// </summary>
-        public bool Draggable { get; set; }
-
-        /// <summary>
-        /// Drag and drop only within the Viewport
-        /// </summary>
-        public bool DragInViewport { get; set; } = true;
-
-        /// <summary>
-        /// closer icon RenderFragment, the default is a "X"
-        /// </summary>
-        public RenderFragment CloseIcon { get; set; } = DialogOptions.DefaultCloseIcon;
-
-        /// <summary>
-        /// Whether to apply loading visual effect for OK button or not
-        /// </summary>
-        public bool ConfirmLoading
-        {
-            get
-            {
-                if (OkButtonProps != null)
-                {
-                    return OkButtonProps.Loading;
-                }
-                return false;
-            }
-            set
-            {
-                if (OkButtonProps == null)
-                {
-                    OkButtonProps = new ButtonProps();
-                }
-
-                OkButtonProps.Loading = value;
-            }
-        }
-
-        /// <summary>
-        /// Whether to remove Modal from DOM after the Modal closed
-        /// </summary>
-        public bool DestroyOnClose { get; set; }
-
-        /// <summary>
-        /// Modal footer. If Footer==null, the dialog will not have a footer
-        /// </summary>
-        public OneOf<string, RenderFragment>? Footer { get; set; } = DialogOptions.DefaultFooter;
-
         /// <summary>
         /// 
         /// </summary>
         public bool Visible { get; set; } = true;
 
-        /// <summary>
-        /// The class name of the container of the modal dialog	
-        /// </summary>
-        public string WrapClassName { get; set; }
-
-        private Func<MouseEventArgs, Task> _onCancel;
 
         /// <summary>
         /// Specify a function that will be called when a user clicks mask, close button on top right or Cancel button.
         /// </summary>
-        public Func<MouseEventArgs, Task> OnCancel { get => _onCancel; set => _onCancel = value; }
+        public override Func<MouseEventArgs, Task> OnCancel { get => _onCancel; set => _onCancel = value; }
 
-        private Func<MouseEventArgs, Task> _onOk;
 
         /// <summary>
         /// Specify a function that will be called when a user clicks the OK button
         /// </summary>
-        public Func<MouseEventArgs, Task> OnOk { get => _onOk; set => _onOk = value; }
-
-        /// <summary>
-        /// ChildContent
-        /// </summary>
-        public RenderFragment Content { get; set; } = null;
-
-        /// <summary>
-        /// show modal maximize button
-        /// </summary>
-        public bool Maximizable { get; set; } = false;
-
-        /// <summary>
-        /// The icon of the maximize button when the modal is in normal state
-        /// </summary>
-        public RenderFragment MaximizeBtnIcon { get; set; } = DialogOptions.DefaultMaximizeIcon;
+        public override Func<MouseEventArgs, Task> OnOk { get => _onOk; set => _onOk = value; }
 
-        /// <summary>
-        /// The icon of the maximize button when the modal is maximized
-        /// </summary>
-        public RenderFragment RestoreBtnIcon { get; set; } = DialogOptions.DefaultRestoreIcon;
-
-        /// <summary>
-        /// Maximize the Modal during component initialization, and it will ignore the Maximizable value.
-        /// </summary>
-        public bool DefaultMaximized { get; set; } = false;
-
-        /// <summary>
-        /// Resizable
-        /// </summary>
-        public bool Resizable { get; set; }
-
-        #region internal
+        public ModalOptions()
+        {
+            _onCancel = DefaultOnCancelOrOk;
+            _onOk = DefaultOnCancelOrOk;
+            Width = 520;
+            MaskClosable = true;
+        }
 
         public async Task DefaultOnCancelOrOk(MouseEventArgs e)
         {
             await (ModalRef?.CloseAsync() ?? Task.CompletedTask);
         }
-
-        #endregion
     }
 }
diff --git a/components/modal/confirmDialog/Confirm.razor.cs b/components/modal/confirmDialog/Confirm.razor.cs
index b42918d811..dd83cf3cad 100644
--- a/components/modal/confirmDialog/Confirm.razor.cs
+++ b/components/modal/confirmDialog/Confirm.razor.cs
@@ -69,7 +69,7 @@ private DialogOptions BuildDialogOptions(ConfirmOptions confirmOptions)
             config.ClassName = "ant-modal-confirm ant-modal-confirm-" + confirmOptions.ConfirmType;
             config.Title = null;
             config.CloseIcon = null;
-            config.OnClosed = Close;
+            config.AfterClose = Close;
             config.OnCancel = ConfirmRef.Config.CreateByService ? e => HandleCancel(e, ConfirmResult.Cancel) : new Func<MouseEventArgs, Task>(async (e) => await Close());
             return config;
         }
diff --git a/components/modal/confirmDialog/ModalServiceForConfirm.cs b/components/modal/confirmDialog/ModalServiceForConfirm.cs
index f38c15403e..3d942928fb 100644
--- a/components/modal/confirmDialog/ModalServiceForConfirm.cs
+++ b/components/modal/confirmDialog/ModalServiceForConfirm.cs
@@ -302,7 +302,7 @@ public Task<ConfirmRef<TResult>> CreateAsync<TComponent, TComponentOptions, TRes
         public Task<ConfirmRef<TResult>> CreateConfirmAsync<TComponent, TComponentOptions, TResult>(ConfirmOptions config, TComponentOptions componentOptions) where TComponent : FeedbackComponent<TComponentOptions, TResult>
         {
             CheckConfirmOptionsIsNull(config);
-
+            config.CreateByService = true;
             ConfirmRef<TResult> confirmRef = new ConfirmRef<TResult>(config, this);
             OnConfirmOpenEvent?.Invoke(confirmRef);
 
diff --git a/components/modal/core/Dialog.razor b/components/modal/core/Dialog.razor
index 2f24e3a297..c48fe695cd 100644
--- a/components/modal/core/Dialog.razor
+++ b/components/modal/core/Dialog.razor
@@ -19,7 +19,7 @@
                  style="@GetStyle()"
                  >
                 <div id="@_sentinelStart" tabindex="0" aria-hidden="true" style="width: 0px; height: 0px; overflow: hidden; outline: none;"></div>
-                <div class=@($"{Config.PrefixCls}-content") style="@(Config.Resizable ? "resize:horizontal; overflow: hidden;":"")" id=@($"{Config.PrefixCls}-wrap_{DialogWrapperId}")>
+                <div class=@($"{Config.PrefixCls}-content") style="@(Config.Resizable ? "resize:horizontal; overflow: hidden;":"")" id=@($"{Config.PrefixCls}-wrap_{Id}")>
                     @if (Config.Header != null)
                     {
                         <CascadingValue Value="@Config">
@@ -31,7 +31,9 @@
                         </CascadingValue>
                     }
                     <div class=@($"{Config.PrefixCls}-body") style="@GetBodyStyle()">
-                        @ChildContent
+                        <CascadingValue Value=@($"#{Config.PrefixCls}-wrap_{Id}") Name="PopupContainerSelector" IsFixed>
+                            @ChildContent
+                        </CascadingValue>
                     </div>
                     @if (Config.Footer != null)
                     {
diff --git a/components/modal/core/Dialog.razor.cs b/components/modal/core/Dialog.razor.cs
index 58098822c8..2a1eaff2da 100644
--- a/components/modal/core/Dialog.razor.cs
+++ b/components/modal/core/Dialog.razor.cs
@@ -350,9 +350,9 @@ internal async Task Hide()
                 _maskHideClsName = "ant-modal-mask-hidden";
 
                 await InvokeStateHasChangedAsync();
-                if (Config.OnClosed != null)
+                if (Config.AfterClose != null)
                 {
-                    await Config.OnClosed.Invoke();
+                    await Config.AfterClose.Invoke();
                 }
             }
         }
@@ -440,8 +440,15 @@ protected override async Task OnAfterRenderAsync(bool isFirst)
                 if (_hasDestroy)
                 {
                     _hasDestroy = false;
-                    await AppendToContainer();
+                    //await AppendToContainer();
                     Show();
+                    CallAfterRender(async () =>
+                    {
+                        if (Config.AfterOpen != null)
+                        {
+                            await Config.AfterOpen.Invoke();
+                        }
+                    });
                     await InvokeStateHasChangedAsync();
                 }
 
@@ -492,7 +499,7 @@ protected override void Dispose(bool disposing)
 
             if (!Config.CreateByService && !Config.DestroyOnClose)
             {
-                _ = JsInvokeAsync(JSInteropConstants.DelElementFrom, "#" + Id, Config.GetContainer);
+                //_ = JsInvokeAsync(JSInteropConstants.DelElementFrom, "#" + Id);
             }
         }
     }
diff --git a/components/modal/modalDialog/Modal.razor b/components/modal/modalDialog/Modal.razor
index 7ff3c21f2a..ff2091fbc3 100644
--- a/components/modal/modalDialog/Modal.razor
+++ b/components/modal/modalDialog/Modal.razor
@@ -1,20 +1,28 @@
 ﻿@namespace AntDesign
+@using Microsoft.AspNetCore.Components.Rendering
 @inherits AntDomComponentBase
 
-<DialogWrapper @ref="_dialogWrapper"
-               Config="@BuildDialogOptions()"
-               Visible="@Visible"
-               OnAfterShow="@OnAfterDialogShow"
-               OnAfterHide="@OnAfterHide"
-               OnBeforeDestroy="@OnBeforeDialogWrapperDestroy"
-               Style="@Style"
-               Class="@Class"
-               Id="@Id">
-    <CascadingValue Value=@($"#ant-modal-wrap_{_dialogWrapper.Id}") Name="PopupContainerSelector">
-        <CascadingValue Value="true" Name="InModal">
-            <CascadingValue Value="@_dialogWrapper.Dialog.IsShow()" Name="ModalCompleteShow">
-                    @ChildContent
-            </CascadingValue>
-        </CascadingValue>
-    </CascadingValue>
-</DialogWrapper>
+@code {
+    internal static RenderFragment GetModalRender(ModalRef modalRef)
+    {
+        var options = modalRef.Config;
+        var attributes = new Dictionary<string, object>()
+        {
+            ["OnOk"] = EventCallback.Factory.Create(modalRef, options.OnOk),
+            ["OnCancel"] = EventCallback.Factory.Create(modalRef, options.OnCancel),
+        };
+
+        void GetRender(RenderTreeBuilder __builder)
+        {
+            <Dialog @ref="modalRef.Dialog" Config="@options"
+                    Visible="@options.Visible"
+                    Style="@options.Style"
+                    Class="@options.ClassName"
+                    >
+                @options.Content
+            </Dialog>
+        }
+
+        return GetRender;
+    }
+}
diff --git a/components/modal/modalDialog/Modal.razor.cs b/components/modal/modalDialog/Modal.razor.cs
index 802d68c46e..50c38c5f65 100644
--- a/components/modal/modalDialog/Modal.razor.cs
+++ b/components/modal/modalDialog/Modal.razor.cs
@@ -12,16 +12,10 @@ namespace AntDesign
     /// <summary>
     /// Modal Dialog
     /// </summary>
-    public partial class Modal
+    public partial class Modal: AntDomComponentBase
     {
         #region Parameter
 
-        /// <summary>
-        ///
-        /// </summary>
-        [Parameter]
-        public ModalRef ModalRef { get; set; }
-
         /// <summary>
         /// Specify a function that will be called when modal is closed
         /// </summary>
@@ -223,11 +217,6 @@ private string GetWidth()
         [Parameter]
         public RenderFragment ChildContent { get; set; }
 
-        /// <summary>
-        /// Is RTL
-        /// </summary>
-        public bool Rtl => base.RTL;
-
         /// <summary>
         /// Modal Locale
         /// </summary>
@@ -270,21 +259,23 @@ private string GetWidth()
         [Parameter]
         public bool Resizable { get; set; } = false;
 
+        public ModalRef ModalRef => _modalRef;
+
         #endregion Parameter
 
-#pragma warning disable 649
-        private DialogWrapper _dialogWrapper;
-#pragma warning restore 649
+        [Inject] private ModalService ModalService { get; set; }
 
-        private DialogOptions BuildDialogOptions()
+        private ModalOptions BuildDialogOptions()
         {
-            DialogOptions options = new DialogOptions()
+            ModalOptions options = new ModalOptions()
             {
-                OnClosed = AfterClose,
+                AfterClose = AfterClose,
+                AfterOpen = OnAfterDialogShow,
                 BodyStyle = BodyStyle,
                 CancelText = CancelText ?? Locale.CancelText,
                 Centered = Centered,
                 Closable = Closable,
+                Content = ChildContent,
                 Draggable = Draggable,
                 DragInViewport = DragInViewport,
                 DestroyOnClose = DestroyOnClose,
@@ -292,13 +283,11 @@ private DialogOptions BuildDialogOptions()
                 ConfirmLoading = ConfirmLoading,
                 Header = Header,
                 Footer = Footer,
-
                 GetContainer = GetContainer,
                 Keyboard = Keyboard,
                 Mask = Mask,
                 MaskClosable = MaskClosable,
                 MaskStyle = MaskStyle,
-
                 OkText = OkText ?? Locale.OkText,
                 OkType = OkType,
                 Title = Title,
@@ -310,13 +299,14 @@ private DialogOptions BuildDialogOptions()
                 {
                     var args = new ModalClosingEventArgs(e, false);
 
-                    var modalTemplate = (ModalRef as IFeedbackRef)?.ModalTemplate;
+                    var modalTemplate = (_modalRef as IFeedbackRef)?.ModalTemplate;
                     if (modalTemplate != null)
                         await modalTemplate.OnFeedbackCancelAsync(args);
                     if (!args.Cancel)
                     {
-                        await (ModalRef?.OnCancel?.Invoke() ?? Task.CompletedTask);
+                        await (_modalRef?.OnCancel?.Invoke() ?? Task.CompletedTask);
 
+                        await _modalRef.CloseAsync();
                         if (VisibleChanged.HasDelegate)
                         {
                             await VisibleChanged.InvokeAsync(false);
@@ -332,21 +322,22 @@ private DialogOptions BuildDialogOptions()
                 {
                     var args = new ModalClosingEventArgs(e, false);
 
-                    var modalTemplate = (ModalRef as IFeedbackRef)?.ModalTemplate;
+                    var modalTemplate = (_modalRef as IFeedbackRef)?.ModalTemplate;
                     if (modalTemplate != null)
                         await modalTemplate.OnFeedbackOkAsync(args);
                     if (!args.Cancel)
                     {
-                        await (ModalRef?.OnOk?.Invoke() ?? Task.CompletedTask);
+                        await (_modalRef?.OnOk?.Invoke() ?? Task.CompletedTask);
 
-                        if (VisibleChanged.HasDelegate)
+                        if (OnOk.HasDelegate)
                         {
-                            await VisibleChanged.InvokeAsync(false);
+                            await OnOk.InvokeAsync(e);
                         }
 
-                        if (OnOk.HasDelegate)
+                        await _modalRef.CloseAsync();
+                        if (VisibleChanged.HasDelegate)
                         {
-                            await OnOk.InvokeAsync(e);
+                            await VisibleChanged.InvokeAsync(false);
                         }
                     }
                     else
@@ -356,16 +347,15 @@ private DialogOptions BuildDialogOptions()
                     }
                 },
                 OkButtonProps = OkButtonProps,
-
                 CancelButtonProps = CancelButtonProps,
-                Rtl = Rtl,
+                Rtl = base.RTL,
                 MaxBodyHeight = MaxBodyHeight,
                 Maximizable = Maximizable,
                 MaximizeBtnIcon = MaximizeBtnIcon,
                 RestoreBtnIcon = RestoreBtnIcon,
                 DefaultMaximized = DefaultMaximized,
                 Resizable = Resizable,
-                CreateByService = ModalRef?.Config.CreateByService ?? false,
+                CreateByService = false,
             };
 
             return options;
@@ -377,15 +367,49 @@ private DialogOptions BuildDialogOptions()
 
         private bool _firstShow = true;
 
+        private ModalRef _modalRef;
+
+        protected override void OnInitialized()
+        {
+            var options = BuildDialogOptions();
+            _modalRef = new ModalRef(options, ModalService);
+
+            base.OnInitialized();
+        }
+
+        public override async Task SetParametersAsync(ParameterView parameters)
+        {
+            if (parameters.IsParameterChanged(nameof(ConfirmLoading), ConfirmLoading, out var newVal))
+            {
+                _modalRef.SetConfirmLoading(newVal);
+            }
+
+            var visibleChanged = parameters.IsParameterChanged(nameof(Visible), Visible, out var newVisible);
+
+            await base.SetParametersAsync(parameters);
+
+            if (visibleChanged)
+            {
+                if (Visible)
+                {
+                    await _modalRef?.OpenAsync();
+                }
+                else
+                {
+                    await _modalRef?.CloseAsync();
+                }
+            }
+        }
+
         private async Task OnAfterDialogShow()
         {
             if (!_hasFocus)
             {
-                await JsInvokeAsync(JSInteropConstants.FocusDialog, $"#{_dialogWrapper.Dialog.SentinelStart}");
+                await JsInvokeAsync(JSInteropConstants.FocusDialog, $"#{_modalRef.Dialog.SentinelStart}");
                 _hasFocus = true;
-                if (ModalRef?.OnOpen != null)
+                if (_modalRef?.OnOpen != null)
                 {
-                    await ModalRef.OnOpen();
+                    await _modalRef.OnOpen();
                 }
             }
         }
@@ -393,9 +417,9 @@ private async Task OnAfterDialogShow()
         private async Task OnAfterHide()
         {
             _hasFocus = false;
-            if (ModalRef?.OnClose != null)
+            if (_modalRef?.OnClose != null)
             {
-                await ModalRef.OnClose();
+                await _modalRef.OnClose();
             }
         }
 
diff --git a/components/modal/modalDialog/ModalContainer.razor b/components/modal/modalDialog/ModalContainer.razor
index a5b62721de..50de5b46cf 100644
--- a/components/modal/modalDialog/ModalContainer.razor
+++ b/components/modal/modalDialog/ModalContainer.razor
@@ -4,45 +4,5 @@
 
 @foreach (ModalRef modalRef in _modalRefs)
 {
-    var options = modalRef.Config;
-
-    <Modal @key="@options"
-       ModalRef="@modalRef"
-       AfterClose="@options.AfterClose"
-       Style="@options.Style"
-       BodyStyle="@options.BodyStyle"
-       CancelText="@options.CancelText"
-       Centered="@options.Centered"
-       Closable="@options.Closable"
-       Draggable="@options.Draggable"
-       DragInViewport="@options.DragInViewport"
-       CloseIcon="@options.CloseIcon"
-       ConfirmLoading="@options.ConfirmLoading"
-       DestroyOnClose="@options.DestroyOnClose"
-       Footer="@options.Footer"
-       GetContainer="@options.GetContainer"
-       Keyboard="@options.Keyboard"
-       Mask="@options.Mask"
-       MaskClosable="@options.MaskClosable"
-       MaskStyle="@options.MaskStyle"
-       OkText="@options.OkText"
-       OkType="@options.OkType"
-       Title="@options.Title"
-       TitleTemplate="@options.TitleTemplate"
-       Visible="@options.Visible"
-       Width="@options.Width"
-       WrapClassName="@options.WrapClassName"
-       ZIndex="@options.ZIndex"
-       OnCancel="@options.OnCancel"
-       OnOk="@options.OnOk"
-       OkButtonProps="@options.OkButtonProps"
-       CancelButtonProps="@options.CancelButtonProps"
-       Maximizable="@options.Maximizable"
-       MaximizeBtnIcon="@options.MaximizeBtnIcon"
-       RestoreBtnIcon="@options.RestoreBtnIcon"
-       DefaultMaximized="@options.DefaultMaximized"
-       Resizable="@options.Resizable"
-       >
-        @options.Content
-    </Modal>
+    @modalRef.Render;
 }
\ No newline at end of file
diff --git a/components/modal/modalDialog/ModalContainer.razor.cs b/components/modal/modalDialog/ModalContainer.razor.cs
index a2aab1846f..566fad3fd0 100644
--- a/components/modal/modalDialog/ModalContainer.razor.cs
+++ b/components/modal/modalDialog/ModalContainer.razor.cs
@@ -1,5 +1,6 @@
 ﻿using System;
 using System.Collections.Generic;
+using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 using Microsoft.AspNetCore.Components;
@@ -27,7 +28,7 @@ protected override void OnInitialized()
 
         private void OnLocationChanged(object sender, EventArgs e)
         {
-            _modalRefs.Clear();
+            _modalRefs.RemoveAll(x => x.Config.CreateByService);
             InvokeStateHasChanged();
         }
 
diff --git a/components/modal/modalDialog/ModalRef.cs b/components/modal/modalDialog/ModalRef.cs
index 91f907c4d2..949af078ff 100644
--- a/components/modal/modalDialog/ModalRef.cs
+++ b/components/modal/modalDialog/ModalRef.cs
@@ -2,6 +2,7 @@
 using System.Collections.Generic;
 using System.Text;
 using System.Threading.Tasks;
+using Microsoft.AspNetCore.Components;
 
 namespace AntDesign
 {
@@ -11,6 +12,7 @@ namespace AntDesign
     public class ModalRef : FeedbackRefWithOkCancelBase
     {
         public ModalOptions Config { get; private set; }
+        internal Dialog Dialog { get; set; }
         private readonly ModalService _service;
 
         internal ModalRef(ModalOptions config, ModalService modalService)
@@ -19,6 +21,8 @@ internal ModalRef(ModalOptions config, ModalService modalService)
             _service = modalService;
         }
 
+        internal RenderFragment Render => Modal.GetModalRender(this);
+
         /// <summary>
         /// open the Modal dialog
         /// </summary>
@@ -29,11 +33,9 @@ public override async Task OpenAsync()
             {
                 Config.Visible = true;
             }
-
             await _service.CreateOrOpenModalAsync(this);
         }
 
-
         /// <summary>
         /// close the Modal dialog
         /// </summary>
@@ -58,6 +60,10 @@ public override async Task UpdateConfigAsync()
         /// <param name="loading"></param>
         public void SetConfirmLoading(bool loading)
         {
+            if (Config.ConfirmLoading == loading)
+            {
+                return;
+            }
             Config.ConfirmLoading = loading;
             _service.UpdateModal(this);
         }
diff --git a/site/AntDesign.Docs/Demos/Components/Modal/demo/CustomModalFooter.razor b/site/AntDesign.Docs/Demos/Components/Modal/demo/CustomModalFooter.razor
index 90dee98f9d..8ae8397fad 100644
--- a/site/AntDesign.Docs/Demos/Components/Modal/demo/CustomModalFooter.razor
+++ b/site/AntDesign.Docs/Demos/Components/Modal/demo/CustomModalFooter.razor
@@ -40,7 +40,7 @@
         _visible = false;
     }
 
-    private async Task OpenModal()
+    private void OpenModal()
     {
         var options = new ModalOptions()
         {
@@ -55,8 +55,6 @@
             await options.DefaultOnCancelOrOk(e);
         };
 
-
-        await modalService.CreateModalAsync(options);
+        modalService.CreateModal(options);
     }
-
 }
\ No newline at end of file


Test patch:
diff --git a/site/AntDesign.Docs/Pages/Test.razor b/site/AntDesign.Docs/Pages/Test.razor
deleted file mode 100644
index 423b78dbd0..0000000000
--- a/site/AntDesign.Docs/Pages/Test.razor
+++ /dev/null
@@ -1,37 +0,0 @@
-﻿@page "/test"
-
-<Input TValue="string" Bordered="false"  Class="methods__inputNumber" />
-
-
-<AutoComplete @bind-Value="@value" Options="@options" OnSelectionChange="OnSelectionChange" OnActiveChange="OnActiveChange" Placeholder="input here" Class="auto" />
-<Divider></Divider>
-<span>bind-Value:@value</span>
-<br />
-<span>SelectedValue:@selectItem?.Value</span>
-<br />
-<span>ActiveValue:@activeItem?.Value</span>
-
-@code
-{
-    private string value;
-
-    List<string> options = new List<string>()
-{
-        "Beijing","Shanghai","Guangzhou","Shenzhen","Chongqing","Wuhan"
-    };
-
-
-    private AutoCompleteOption selectItem;
-
-    void OnSelectionChange(AutoCompleteOption item)
-    {
-        selectItem = item;
-    }
-
-    private AutoCompleteOption activeItem;
-
-    void OnActiveChange(AutoCompleteOption item)
-    {
-        activeItem = item;
-    }
-}
\ No newline at end of file