ASP.NET Core 7 模型在模态弹出窗口上出现错误。

huangapple go评论89阅读模式
英文:

ASP.NET Core 7 MVC model errors on modal popup

问题

以下是您要翻译的内容:

我的索引视图使用 List<Rental> 作为其模型,并显示所有租赁对象。期望的场景:用户点击“Filter!”按钮,一个模态弹出窗口显示,用户选择一些选项,点击“Submit”,然后,如果模型状态无效,模态弹出窗口保持显示并显示错误,否则,我们将以不同(经过筛选的)租赁列表作为模型加载索引视图。

Index.cshtml,用于显示模态弹出窗口的模态弹出窗口和“Filter!”按钮:

<div id="filterModal" class="modal" tabindex="-1">
	<div class="modal-dialog modal-xl"></div>
</div>

<button id="filterButton" class="btn btn-outline-light" type="button">Filter!</button>

Index.cshtml,用于显示模态弹出窗口的jQuery代码:

<script>
	$('#filterButton').click(function () {
		$('#filterModal .modal-dialog').load('/Home/GetFilterPartial');
		$('#filterModal').modal('show');
	});
</script>

HomeController.cs,用于呈现索引页面和模态弹出窗口的方法:

[HttpGet]
[Route("/")]
public async Task<IActionResult> IndexAsync()
{
	// 获取所有租赁列表

	return View(model);
}

[HttpPost]
[Route("/Results")]
public async Task<IActionResult> IndexAsync(FilterViewModel vm)
{
	if (ModelState.IsValid)
	{
		// 根据弹出窗口的视图模型进行筛选

		return View(await rentals.ToListAsync()); // 使用合适的弹出窗口视图模型,返回经过筛选的租赁列表的索引
	}

	return PartialView("_FilterPartial", vm); // 错误的弹出窗口视图模型,保持在弹出窗口上并显示问题
}

[HttpGet]
public async Task<IActionResult> GetFilterPartialAsync()
{
	return PartialView("_FilterPartial");
}

_FilterPartial.cshtml:

@model FilterViewModel

<div class="modal-content">
	<form asp-controller="Home" asp-action="Index" id="filterForm" method="post">
		<div class="modal-header">
			<h5 class="modal-title">Wanna filter?</h5>
			<button class="btn-close" type="button" data-bs-dismiss="modal"></button>
		</div>
		<div class="modal-body d-grid gap-3">
			<div class="row">
				<div asp-validation-summary="ModelOnly" class="text-danger"></div>
			</div>
			
			<!-- 这里是一些 FilterViewModel 的输入字段 -->
		</div>
		<div class="modal-footer">
			<button class="btn btn-secondary" type="button" data-bs-dismiss="modal">Close</button>
			<button class="btn btn-primary">Submit</button>
		</div>
	</form>
</div>

模态弹出窗口会显示,但如果存在模型错误,IndexAsync(FilterViewModel vm) 方法会返回 _FilterPartial,而该部分视图会独立显示(不作为模态弹出窗口或索引视图的一部分)。我只是不明白如何将带有模型错误的部分视图返回到模态弹出窗口,而不影响我们返回视图的其他情况。

希望这对您有所帮助!

英文:

My Index view uses List&lt;Rental&gt; as it's model, and I display all Rental objects. The desired scenario: user clicks on "Filter!" button, a modal popup shows up, user selects some options, clicks "Submit", then, if the model state is invalid, the modal popup stays and displays the errors, otherwise, we load the Index view with different (filtered) list of rentals as model.

Index.cshtml, the modal popup and "Filter!" button for displaying it:

&lt;div id=&quot;filterModal&quot; class=&quot;modal&quot; tabindex=&quot;-1&quot;&gt;
	&lt;div class=&quot;modal-dialog modal-xl&quot;&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;button id=&quot;filterButton&quot; class=&quot;btn btn-outline-light&quot; type=&quot;button&quot;&gt;Filter!&lt;/button&gt;

Index.cshtml, jQuery for displaying the modal popup:

&lt;script&gt;
	$(&#39;#filterButton&#39;).click(function () {
		$(&#39;#filterModal .modal-dialog&#39;).load(&#39;/Home/GetFilterPartial&#39;);
		$(&#39;#filterModal&#39;).modal(&#39;show&#39;);
	});
&lt;/script&gt;

HomeController.cs, methods for rendering the Index page and the modal popup:

[HttpGet]
[Route(&quot;/&quot;)]
public async Task&lt;IActionResult&gt; IndexAsync()
{
	//I get the list of all rentals

	return View(model);
}

[HttpPost]
[Route(&quot;/Results&quot;)]
public async Task&lt;IActionResult&gt; IndexAsync(FilterViewModel vm)
{
	if (ModelState.IsValid)
	{
		//I do some filtering based on the popup&#39;s view model

		return View(await rentals.ToListAsync()); //GOOD POPUP&#39;S VIEWMODEL, RETURN INDEX WITH FILTERED RENTALS
	}

	return PartialView(&quot;_FilterPartial&quot;, vm); //BAD POPUP&#39;S VIEWMODEL, STAY ON THE POPUP &amp; SHOW WHAT&#39;S WRONG
}

[HttpGet]
public async Task&lt;IActionResult&gt; GetFilterPartialAsync()
{
	return PartialView(&quot;_FilterPartial&quot;);
}

_FilterPartial.cshtml:

@model FilterViewModel

&lt;div class=&quot;modal-content&quot;&gt;
	&lt;form asp-controller=&quot;Home&quot; asp-action=&quot;Index&quot; id=&quot;filterForm&quot; method=&quot;post&quot;&gt;
		&lt;div class=&quot;modal-header&quot;&gt;
			&lt;h5 class=&quot;modal-title&quot;&gt;Wanna filter?&lt;/h5&gt;
			&lt;button class=&quot;btn-close&quot; type=&quot;button&quot; data-bs-dismiss=&quot;modal&quot;&gt;&lt;/button&gt;
		&lt;/div&gt;
		&lt;div class=&quot;modal-body d-grid gap-3&quot;&gt;
			&lt;div class=&quot;row&quot;&gt;
				&lt;div asp-validation-summary=&quot;ModelOnly&quot; class=&quot;text-danger&quot;&gt;&lt;/div&gt;
			&lt;/div&gt;
			
			&lt;!--- here are some input fields for FilterViewModel ---&gt;
		&lt;/div&gt;
		&lt;div class=&quot;modal-footer&quot;&gt;
			&lt;button class=&quot;btn btn-secondary&quot; type=&quot;button&quot; data-bs-dismiss=&quot;modal&quot;&gt;Close&lt;/button&gt;
			&lt;button class=&quot;btn btn-primary&quot;&gt;Submit&lt;/button&gt;
		&lt;/div&gt;
	&lt;/form&gt;
&lt;/div&gt;

The modal popup shows, but if there are model errors, the IndexAsync(FilterViewModel vm) method returns the _FilterPartial, and that partial view is shown independently (not as part of modal popup or Index view). I just don't understand how to return a partial view with model errors back to the modal popup, not affecting another scenario where we would return a view.

Any help is greatly appreciated!!!

答案1

得分: 1

You should refresh your modal popup with Ajax instead of submitting the form.

I tried as below:

Partial Viewmodel:

public class PartialVM
{
    public int Id { get; set; }
    [Required]
    public string? Prop1 { get; set; }
    [Required]
    public string? Prop2 { get; set; }
    [Required]
    public string? Prop3 { get; set; }
}

_FilterPartial:

@model PartialVM

<div class="modal-content">
    <form asp-controller="Home" asp-action="Index" id="filterForm" method="post">
        <div class="modal-header">
            <h5 class="modal-title">Wanna filter?</h5>
            <button class="btn-close" type="button" data-bs-dismiss="modal"></button>
        </div>
        <div class="modal-body d-grid gap-3">
            <div class="row">
                <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            </div>
            <label asp-for="Id" class="control-label"></label>
            <input asp-for="Id"/>
            <label asp-for="Prop1" class="control-label"></label>
            <input asp-for="Prop1" class="form-control" />
            <span asp-validation-for="Prop1" class="text-danger"></span>
            <label asp-for="Prop2" class="control-label"></label>
            <input asp-for="Prop2" class="form-control" />
            <span asp-validation-for="Prop2" class="text-danger"></span>
            <label asp-for="Prop3" class="control-label"></label>
            <input asp-for="Prop3" class="form-control" />
            <span asp-validation-for="Prop3" class="text-danger"></span>

            <!--- here are some input fields for FilterViewModel --->
        </div>
        <div class="modal-footer">
            <button class="btn btn-secondary" type="button" data-bs-dismiss="modal">Close</button>
            <button class="btn btn-primary">Submit</button>
        </div>
    </form>
</div>

<script>
    $("#filterForm").submit(function (e) {
        e.preventDefault(); 
        var form = $(this);
        var actionUrl = form.attr('action');
        $.ajax({
            type: "POST",
            url: actionUrl,
            data: form.serialize(), 
            success: function (data) {
                $('#filterModal .modal-dialog').html(data)
            }
        });
    });
</script>

Result:

ASP.NET Core 7 模型在模态弹出窗口上出现错误。

Check the issue again, modified my codes for your requirement:

Controller:

public IActionResult Index(int[] id)
{
    // filter with id or something else
    if (id.Count() != 0)
    {

    }
    
    return View();
}

[HttpPost]
public async Task<IActionResult> Index(PartialVM partialVM)
{
    if (ModelState.IsValid)
    {
        return new JsonResult(
            new { 
                valid=true,
                url=HttpContext.Request.PathBase+"Home/Index?id=1&id=2&id=3"
            });
    }
    else
    {
        this.ViewData.Model = partialVM;
        using StringWriter sw = new StringWriter();
        IView view = _viewEngine.FindView(ControllerContext, "_filterPartial", false).View;
        ViewContext viewContext = new ViewContext(ControllerContext, view, ViewData, TempData, sw, new HtmlHelperOptions());
        await view.RenderAsync(viewContext);
        var content = sw.GetStringBuilder().ToString();


        return new JsonResult(new
        {
            valid = false,
            content = content
        });
        // return PartialView("_FilterPartial", partialVM);
    }
}

Jquery codes:

<script>
    $("#filterForm").submit(function (e, ban) {     
        
        if(ban!=false){
            e.preventDefault();
        }     
        
        var form = $(this);
        var actionUrl = form.attr('action');
        $.ajax({
            type: "POST",
            url: actionUrl,
            data: form.serialize(), 
            success: function (data) {
                console.log(data)
                if(data.valid){
                    window.location.assign(data.url)
                }
                else{
                    $('#filterModal .modal-dialog').html(data.content)
                }                
            }
        });
    });
</script>

Now Result:

ASP.NET Core 7 模型在模态弹出窗口上出现错误。

英文:

You should refresh your modal popup with Ajax instead of sumbit the form

I tried as below:

partial Viewmodel:

 public class PartialVM
    {
        public int Id { get; set; }
        [Required]
        public string? Prop1 { get; set; }
        [Required]
        public string? Prop2 { get; set; }
        [Required]
        public string? Prop3 { get; set; }
    }

_FilterPartial :

@model PartialVM

&lt;div class=&quot;modal-content&quot;&gt;
    &lt;form asp-controller=&quot;Home&quot; asp-action=&quot;Index&quot; id=&quot;filterForm&quot; method=&quot;post&quot;&gt;
        &lt;div class=&quot;modal-header&quot;&gt;
            &lt;h5 class=&quot;modal-title&quot;&gt;Wanna filter?&lt;/h5&gt;
            &lt;button class=&quot;btn-close&quot; type=&quot;button&quot; data-bs-dismiss=&quot;modal&quot;&gt;&lt;/button&gt;
        &lt;/div&gt;
        &lt;div class=&quot;modal-body d-grid gap-3&quot;&gt;
            &lt;div class=&quot;row&quot;&gt;
                &lt;div asp-validation-summary=&quot;ModelOnly&quot; class=&quot;text-danger&quot;&gt;&lt;/div&gt;
            &lt;/div&gt;
            &lt;label asp-for=&quot;Id&quot; class=&quot;control-label&quot;&gt;&lt;/label&gt;
            &lt;input asp-for=&quot;Id&quot;/&gt;
            &lt;label asp-for=&quot;Prop1&quot; class=&quot;control-label&quot;&gt;&lt;/label&gt;
            &lt;input asp-for=&quot;Prop1&quot; class=&quot;form-control&quot; /&gt;
            &lt;span asp-validation-for=&quot;Prop1&quot; class=&quot;text-danger&quot;&gt;&lt;/span&gt;
            &lt;label asp-for=&quot;Prop2&quot; class=&quot;control-label&quot;&gt;&lt;/label&gt;
            &lt;input asp-for=&quot;Prop2&quot; class=&quot;form-control&quot; /&gt;
            &lt;span asp-validation-for=&quot;Prop2&quot; class=&quot;text-danger&quot;&gt;&lt;/span&gt;
            &lt;label asp-for=&quot;Prop3&quot; class=&quot;control-label&quot;&gt;&lt;/label&gt;
            &lt;input asp-for=&quot;Prop3&quot; class=&quot;form-control&quot; /&gt;
            &lt;span asp-validation-for=&quot;Prop3&quot; class=&quot;text-danger&quot;&gt;&lt;/span&gt;
            

            &lt;!--- here are some input fields for FilterViewModel ---&gt;
        &lt;/div&gt;
        &lt;div class=&quot;modal-footer&quot;&gt;
            &lt;button class=&quot;btn btn-secondary&quot; type=&quot;button&quot; data-bs-dismiss=&quot;modal&quot;&gt;Close&lt;/button&gt;
            &lt;button class=&quot;btn btn-primary&quot;&gt;Submit&lt;/button&gt;
        &lt;/div&gt;
    &lt;/form&gt;
&lt;/div&gt;


&lt;script&gt;
    $(&quot;#filterForm&quot;).submit(function (e) {
        e.preventDefault(); 
        var form = $(this);
        var actionUrl = form.attr(&#39;action&#39;);
        $.ajax({
            type: &quot;POST&quot;,
            url: actionUrl,
            data: form.serialize(), 
            success: function (data) {
                $(&#39;#filterModal .modal-dialog&#39;).html(data)
            }
        });
    });
&lt;/script&gt;

Result:

ASP.NET Core 7 模型在模态弹出窗口上出现错误。

Check the issue again,modified my codes for your requirement:

Controller:

public IActionResult Index(int[] id)
        {
            //filter with id or something else
            if (id.Count() != 0)
            {

            }
            
            return View();
        }
        [HttpPost]
        public async Task&lt;IActionResult&gt; Index(PartialVM partialVM)
        {
            if (ModelState.IsValid)
            {
                return new JsonResult(
                    new { 
                        valid=true,
                        url=HttpContext.Request.PathBase+&quot;Home/Index?id=1&amp;id=2&amp;id=3&quot;
                    });
            }
            else
            {
                this.ViewData.Model = partialVM;
                using StringWriter sw = new StringWriter();
                IView view = _viewEngine.FindView(ControllerContext, &quot;_filterPartial&quot;, false).View;
                ViewContext viewContext = new ViewContext(ControllerContext, view, ViewData, TempData, sw, new HtmlHelperOptions());
                await view.RenderAsync(viewContext);
                var content = sw.GetStringBuilder().ToString();


                return new JsonResult(new
                {
                    valid = false,
                    content = content
                });
                //return PartialView(&quot;_FilterPartial&quot;, partialVM);
            }

        }

Jquery codes:

&lt;script&gt;
    $(&quot;#filterForm&quot;).submit(function (e, ban) {     
        
        if(ban!=false){
            e.preventDefault();
        }     
          
         
        var form = $(this);
        var actionUrl = form.attr(&#39;action&#39;);
        $.ajax({
            type: &quot;POST&quot;,
            url: actionUrl,
            data: form.serialize(), 
            success: function (data) {
                console.log(data)
                if(data.valid){
                    window.location.assign(data.url)
                    
                }
                else{
                    $(&#39;#filterModal .modal-dialog&#39;).html(data.content)
                }
                
            }
        });
    });
&lt;/script&gt;

Now Result:
ASP.NET Core 7 模型在模态弹出窗口上出现错误。

huangapple
  • 本文由 发表于 2023年5月25日 08:37:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/76328203.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定