【问题标题】:Render multiple partial views with the same model in one request在一个请求中渲染多个具有相同模型的局部视图
【发布时间】:2020-12-27 07:03:13
【问题描述】:

假设我有 3 个局部视图,它们都采用相同的模型,并且应该同时渲染/更新。即

<div id="Partial_view1">
    @{ await Html.RenderPartialAsync("partialview1", Model); }
</div>
<div class="Partial_view2">
    @{ await Html.RenderPartialAsync("partialview2", Model); }
</div>
<div class="Partial_view3">
    @{ await Html.RenderPartialAsync("partialview3", Model); }
</div>

目前,当我想使用 jQuery 和 AJAX 更新部分视图时,我通常分别使用父 div、url 和可能的 ID 调用以下函数:

var updatePartialView = function (url, data, hook) {
    $.ajax({
        url: url,
        type: 'GET',
        data: data,
        success: function (response) {
            hook.html(response);
        }
    });
}

可能看起来像这样:

helper.updatePartialView('/Controller', 2, $('#Partial_view1'))

然后控制器通常会返回一个局部视图结果,其中自然返回一个局部视图和一个模型,我将其嵌套在局部视图的包含 div 下方。

//From controller
return PartialView("partialview1", Model);

我想减少对我的服务器的有效负载,因此我对进行 3 个几乎相同的调用不感兴趣。因此我想了解,如果有某种方式可以从中获取模型控制器,然后在 jquery 中填充 3 个局部视图。

提前致谢

【问题讨论】:

  • 如果是同一个模型,为什么还要使用局部视图?既然您想通过 AJAX 进行操作,那么是什么阻止您从 Controller 获取所需的任何模型数据?我想我是在说...我不明白你的问题。
  • 我猜你这里不需要三个局部视图。由于是同一个模型,所以只使用一个部分视图来组合所有这些。

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


【解决方案1】:

因为你的三个部分视图在同一个页面中,所以你只需使用return View("MainPage",model)用更新的模型更新主页而不是使用return PartialView("PartialViewName",model)

但是这种方式有一个缺点,如果你在剃刀视图中使用布局。它会显示重复的导航栏。

Index.cshtml:

@model IEnumerable<Test>
<div id="view_all">
    <div id="Partial_view1">
        @{ await Html.RenderPartialAsync("partialview1", Model); }
    </div>
    <div class="Partial_view2">
        @{ await Html.RenderPartialAsync("partialview2", Model); }
    </div>
    <div class="Partial_view3">
        @{ await Html.RenderPartialAsync("partialview3", Model); }
    </div>
    <input type="button" onclick="Update()" value="Update" />
</div>
@section Scripts
{
    <script>
        function Update() {
            updatePartialView('/Home/Update', 2)
        }    
        var updatePartialView = function (url, data) {
            $.ajax({
                url: url+"?id="+data,
                type: 'GET',
                success: function (response) {
                    $('#view_all').html(response);
                }
            });
        }
    </script>
}

控制器:

public class HomeController : Controller
{
    private List<Test> model = new List<Test>()
        {
            //....
        };

    public IActionResult Index()
    {
        return View(model);
    }
    public IActionResult Update(int id)
    {
        //change the model by yourself
        var test2 = model.Where(a=>a.Id==id).FirstOrDefault();
        test2.Number = 9;
        model[0].Test1.Category = "aaaaaaaa";
        model[2].Test2.Age = "34343434";

        return View("Index", model);
    }
}

第二个选项我认为您可以自定义一个 RenderRazorViewToString 函数,该函数可以将视图解析为字符串,如下所示:

型号:

public class Test
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Number { get; set; }
    public Test1 Test1 { get; set; }        
    public Test2 Test2 { get; set; }        
}
public class Test1
{
    public string Category { get; set; }
}
public class Test2
{
    public string Age { get; set; }
}

Index.cshtml:

@model IEnumerable<Test>
//...
<input type="button" onclick="Update()" value="Update" />

@section Scripts
{
    <script>
        function Update() {
            updatePartialView('/Home/Update', 2)
        }
        
        var updatePartialView = function (url, data) {
            $.ajax({
                url: url+"?id="+data,
                type: 'GET',
                success: function (response) {
                    $('#Partial_view1').html(response.view1);
                    $('.Partial_view2').html(response.view2);
                    $('.Partial_view3').html(response.view3);
                }
            });
        }
    </script>
}

partialview1.cshtml:

@model IEnumerable<Test>
<h1>Test</h1>
<table class="table">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.Number)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Name)
            </th>
        </tr>
    </thead>
    <tbody>
        @foreach (var item in Model)
        {
            <tr>
                <td>
                    @Html.DisplayFor(modelItem => item.Number)
                </td> 
                <td>
                    @Html.DisplayFor(modelItem => item.Name)
                </td>               
            </tr>
        }
    </tbody>
</table>

partialview2.cshtml:

@model IEnumerable<Test>
<h1>Test1</h1>
<table class="table">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.Test1.Category)
            </th>
        </tr>
    </thead>
    <tbody>
        @foreach (var item in Model)
        {
            <tr>
                <td>
                    @Html.DisplayFor(modelItem => item.Test1.Category)
                </td>
            </tr>
        }
    </tbody>
</table>

partialview3.cshtml:

@model IEnumerable<Test>
<h1>Test2</h1>
<table class="table">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.Test2.Age)
            </th>
        </tr>
    </thead>
    <tbody>
        @foreach (var item in Model)
        {
            <tr>
                <td>
                    @Html.DisplayFor(modelItem => item.Test2.Age)
                </td>
            </tr>
        }
    </tbody>
</table>

控制器:

public IActionResult Update(int id)
{
    //change your model by yourself
   
    //pass the updated model to the partial view
    var view1 = Helper.RenderRazorViewToString(this, "partialview1", model);
    var view2 = Helper.RenderRazorViewToString(this, "partialview2", model);
    var view3 = Helper.RenderRazorViewToString(this, "partialview3", model);
    return Json(new { view1 = view1, view2 = view2, view3 = view3 });
}

RenderRazorViewToString 方法:

public class Helper
{
    public static string RenderRazorViewToString(Controller controller, string viewName, object model = null)
    {
        controller.ViewData.Model = model;
        using (var sw = new StringWriter())
        {
            IViewEngine viewEngine =
                controller.HttpContext.RequestServices.GetService(typeof(ICompositeViewEngine)) as
                    ICompositeViewEngine;
            ViewEngineResult viewResult = viewEngine.FindView(controller.ControllerContext, viewName, false);

            ViewContext viewContext = new ViewContext(
                controller.ControllerContext,
                viewResult.View,
                controller.ViewData,
                controller.TempData,
                sw,
                new HtmlHelperOptions()
            );
            viewResult.View.RenderAsync(viewContext);
            return sw.GetStringBuilder().ToString();
        }
    }
}

结果:

对了,这三个局部视图依赖于同一个模型,你为什么把它们放在一起作为一个局部视图?

【讨论】:

  • 感谢您的详尽回答。将其全部移至 1 个部分视图是一个有效点。但是,由于各种不同的原因,这可能不可行。不过我会考虑,因为即使你提出了一些可行的解决方案,我觉得它们中的任何一个都不是最佳的
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-23
  • 1970-01-01
  • 2013-04-18
  • 1970-01-01
  • 1970-01-01
  • 2020-06-29
相关资源
最近更新 更多