【问题标题】:ASP.NET Core 3.1 Razor pages - adding different child objects to headerASP.NET Core 3.1 Razor 页面 - 将不同的子对象添加到标题
【发布时间】:2021-01-27 17:27:30
【问题描述】:

我是网络应用程序开发的新手,我想知道是否有人可以为我指明正确的方向?我想我知道问题出在哪里,但我不知道如何解决它。

我拥有的是一个复杂的模型,其中标题可以包含一个孩子,每个孩子本身可以有自己的孩子(不同类型)。

这里显示的我的演示代码有一个标题和两个列表。如果我单击按钮将子项目添加到第一个列表或第二个列表,我遇到的最初问题是这些项目没有出现。另一个问题是我似乎无法继续向任一列表添加项目。

为了尝试查看发生了什么,我添加了一个部分来显示 innerHTML 以查看数据是什么 - 这说明如果我单击添加到第一个列表,第一个列表会出现一些数据,但是如果我点击添加到第二个列表,新数据将从第一个列表中消失,而新项目按预期显示在第二个列表中。

我认为问题在于模型没有更新以反映新项目 - 但我知道我们无论如何都不应该使用 Javascript 来做到这一点。所以,我想我需要把我所有的局部视图分开,所以我有一个包含很多局部视图的主局部视图,当我的 Ajax 调用成功时,刷新主局部视图。

我的 PageModel 类

namespace ParentChildDemo.Pages
{
    public class IndexModel : PageModel
    {
        private readonly ILogger<IndexModel> _logger;

        [BindProperty]
        public Header MyHeader { get; set; } = new Header();

        public IndexModel(ILogger<IndexModel> logger)
        {
            _logger = logger;
        }

        public void OnGet()
        {
            MyHeader.Id = 1;
            MyHeader.MyHeaderProperty = "HeaderTest1";
            MyHeader.ChildOfHeader.Add(new ChildOfHeader());

            for (int i = 1; i <= 3; i++)
            {
                var childOfChild = new ChildOfChild()
                {
                    Id = i,
                    HeaderId = MyHeader.Id,
                    MyChildProperty = $"FirstChildTest{i}"
                };

                MyHeader.ChildOfHeader[0].MyFirstChildList.Add(childOfChild);
            }

            for (int i = 1; i <= 2; i++)
            {
                var childOfChild = new ChildOfChild()
                {
                    Id = i,
                    HeaderId = MyHeader.Id,
                    MyChildProperty = $"SecondChildTest{i}"
                };

                MyHeader.ChildOfHeader[0].MySecondChildList.Add(childOfChild);
            }
        }

        public PartialViewResult OnPostAddNewFirstListChildItem([FromBody] Header myHeader)
        {
            if (myHeader.ChildOfHeader[0].MyFirstChildList == null)
                myHeader.ChildOfHeader[0].MyFirstChildList = new List<ChildOfChild>();

            var childId = myHeader.ChildOfHeader[0].MyFirstChildList.Count + 1;

            myHeader.ChildOfHeader[0].MyFirstChildList.Add(new ChildOfChild
            {
                Id = childId,
                HeaderId = myHeader.Id,
                MyChildProperty = $"FirstChildTest{childId}"
            });

            var partialView = "_ListPartialView";
            //var partialView = "_FirstListItemPartial";

            var data = new IndexModel(_logger);
            data.MyHeader = myHeader;

            var myViewData = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary()) { { partialView, myHeader } };
            //var myViewData = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary()) { { partialView, myHeader.ChildOfHeader[0].MyFirstChildList } };
            myViewData.Model = data;

            var partialViewResult = new PartialViewResult()
            {
                ViewName = partialView,
                ViewData = myViewData,
            };

            return partialViewResult;
        }

        public PartialViewResult OnPostAddNewSecondListChildItem([FromBody] Header myHeader)
        {
            if (myHeader.ChildOfHeader[0].MySecondChildList == null)
                myHeader.ChildOfHeader[0].MySecondChildList = new List<ChildOfChild>();

            var childId = myHeader.ChildOfHeader[0].MySecondChildList.Count + 1;

            myHeader.ChildOfHeader[0].MySecondChildList.Add(new ChildOfChild
            {
                Id = childId,
                HeaderId = myHeader.Id,
                MyChildProperty = $"SecondChildTest{childId}"
            });

            var partialView = "_ListPartialView";
            //var partialView = "_SecondListItemPartial";

            var data = new IndexModel(_logger);
            data.MyHeader = myHeader;

            var myViewData = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary()) { { partialView, myHeader } };
            //var myViewData = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary()) { { partialView, myHeader.ChildOfHeader[0].MySecondChildList } };
            myViewData.Model = data;

            var partialViewResult = new PartialViewResult()
            {
                ViewName = partialView,
                ViewData = myViewData,
            };

            return partialViewResult;
        }
    }

    public class Header
    {
        public int Id { get; set; }
        public string MyHeaderProperty { get; set; }
        public List<ChildOfHeader> ChildOfHeader { get; set; } = new List<ChildOfHeader>();
    }

    public class ChildOfHeader
    {
        public List<ChildOfChild> MyFirstChildList { get; set; } = new List<ChildOfChild>();
        public List<ChildOfChild> MySecondChildList { get; set; } = new List<ChildOfChild>();
    }

    public class ChildOfChild
    {
        public int Id { get; set; }
        public int HeaderId { get; set; }
        public string MyChildProperty { get; set; }
    }
}

我的索引页面

@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}

<div class="text-center">
    <h1 class="display-4">Welcome</h1>
    <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>

<div>
    <a class="btn btn-sm btn-info text-white" onclick="AddListItem(1)">Add Child to First list</a>
    <a class="btn btn-sm btn-info text-white" onclick="AddListItem(2)">Add Child to Second list</a>
</div>

<br />

<div>
    <div><b>MyHeaderProperty value:</b> @Model.MyHeader.MyHeaderProperty</div>
    <br />
    <div class="container">
        <div class="row">
            <div class="col-6 font-weight-bold">First List</div>
            <div class="col-6 font-weight-bold">Second List</div>
        </div>
        <div class="ListPartialView">
            <partial name="_ListPartialView" model="@Model" />
        </div>
    </div>
    <br />
    <div class="bg-warning" id="HtmlContent"></div>
    
    @Html.AntiForgeryToken()
</div>

<script type="text/javascript">
    function AddListItem(listNumber) {
        var model = @Json.Serialize(Model.MyHeader);

        var handler;
        var partialView;

        if (listNumber == 1) {
            handler = "?handler=AddNewFirstListChildItem";
            partialView = "#ListPartialView";//"#FirstListPartial";
        }
        else {
            handler = "?handler=AddNewSecondListChildItem";
            partialView = "#ListPartialView";//"#SecondListPartial";
        }

        $.ajax({
            type: "POST",
            url: handler,
            data: JSON.stringify(model),
            dataType: "html",
            contentType: "application/json",
            headers: {
                RequestVerificationToken: $('input:hidden[name="__RequestVerificationToken"]').val()
            },
            success: function (result) {
                document.getElementById("HtmlContent").innerHTML = result.toString();
                $(partialView).html(result);
            },
            failure: function (result) {
                alert("Failed");
            }
        });
    }
</script>

我的主要部分视图 (_ListPartialView)

@model IndexModel

@for (int i = 0; i < Model.MyHeader.ChildOfHeader.Count; i++)
{
    ViewData["ChildIndex"] = i;

    <div class="row">
        <div id="FirstListPartial" class="col-6">
            <partial name="_FirstListItemPartial" model="@Model" view-data="ViewData" />
        </div>
        <div id="SecondListPartial" class="col-6">
            <partial name="_SecondListItemPartial" model="@Model" view-data="ViewData" />
        </div>
    </div>
}

我的第一个列表部分视图 (_FirstListItemPartial)

@model IndexModel

@{ 
    var indexId = (int)ViewData["ChildIndex"];
}


<table>
    @foreach (var myChildItem in Model.MyHeader.ChildOfHeader[indexId].MyFirstChildList)
    {
        <tr>
            <td>@myChildItem.Id</td>
            <td>@myChildItem.MyChildProperty</td>
        </tr>
    }
</table>

我的第二个列表部分视图(_SecondListItemPartial)

@model IndexModel

@{
    var indexId = (int)ViewData["ChildIndex"];
}

<table>
    @foreach (var myChildItem in Model.MyHeader.ChildOfHeader[indexId].MySecondChildList)
    {
        <tr>
            <td>@myChildItem.Id</td>
            <td>@myChildItem.MyChildProperty</td>
        </tr>
    }
</table>

任何帮助将不胜感激。

【问题讨论】:

  • data: JSON.stringify(model), 可以是 data: model,,因为 jQuery 会自动执行此操作。 url: handler, 这里你的handler 对象不是一个url,而只是一个参数——它应该是传递的数据的一部分吗?您调用什么控制器方法来返回 JSON(例如 JsonResult 或类似的 IActionResult 等之一。docs.microsoft.com/en-us/aspnet/core/web-api/advanced/… 顺便说一句,您将 jQuery 放在页面的哪个位置?将该 JavaScript 移动到单独的文件并链接到那个而不是页面上的所有内容
  • 您可能只有&lt;script&gt; var model = @Json.Serialize(Model.MyHeader);&lt;/script&gt;,但它的真正用途是什么?在这种情况下这样做似乎不合适?
  • 为什么模型中没有这个? @{ var indexId = (int)ViewData["ChildIndex"]; } 一个问题几乎无法涵盖。
  • 感谢您的 cmets。我的项目不是 MVC 项目(我认为它被称为 MVVM 项目?),所以它没有任何控制器。我按照建议将data: JSON.stringify(model) 换成了data: model,但是在我的 OnPostAddNewFirstListChildItem 方法中出现了这个错误,因为 myHeader 为空。我仍处于了解这一点的早期阶段,所以目前我不确定如何以其他方式传递我的数据。在我真正的解决方案中,我有分离 - 所以我的 Javascript 是分离的。我只是为这个演示尽可能简洁地提供了所有内容。
  • MVVM 确实是一种设计模式,因此只是 MVC 之上的一个抽象层 - 从简单的角度来看,但值得注意的是,从同样简单的角度来看,ViewModel 只是抽象视图的 DTO if from the model 将该模型与 UI 分开。

标签: c# asp.net-core partial-views


【解决方案1】:

如果我点击添加到第一个列表,第一个会出现一些数据 列表,但如果我点击添加到第二个列表,新数据 从第一个列表中消失,而新项目按预期出现 在第二个列表中。

如果在 AddListItem() 函数或 OnPostAddNewSecondListChildItem() 方法中设置断点,您会发现 myHeader 对象是原始对象,它不包含新项目。我认为这个问题与您使用 JQuery ajax 加载部分视图有关,索引页面未刷新且模型未更新,因此,当使用此脚本(var model = @Json.Serialize(Model.MyHeader);)获取模型数据时,它将总是得到原始值。

为了解决这个问题,你可以尝试使用 session 来存储最新的数据,在添加新项目之前,你可以先获取最新的数据,然后再添加新的项目。

如下更改您的代码(更新):

    <script type="text/javascript">
        function AddListItem(listNumber) {
            //var model = @Json.Serialize(Model.MyHeader);  
            var model;
            //get the latest daa
            $.ajax({
                type: "get",
                url: "?handler=GetLatestData",
                async: false,
                contentType: "application/json", 
                success: function (data) {
                    model = data;
                }
            });  
            var handler;
            var partialView;

            if (listNumber == 1) {
                handler = "?handler=AddNewFirstListChildItem";
                partialView = "#FirstListPartial";//"#ListPartialView";
            }
            else {
                handler = "?handler=AddNewSecondListChildItem";
                partialView = "#SecondListPartial";//"#SecondListPartial";
            }

            $.ajax({
                type: "POST",
                url: handler,
                data: JSON.stringify(model),
                dataType: "html",
                contentType: "application/json",
                headers: {
                    RequestVerificationToken: $('input:hidden[name="__RequestVerificationToken"]').val()
                },
                success: function (result) {
                    //document.getElementById("HtmlContent").innerHTML = result.toString();
                    $(partialView).html("");
                    $(partialView).html(result);
                },
                failure: function (result) {
                    alert("Failed");
                }
            });
        }
    </script>

和:

    public void OnGet()
    {
        MyHeader.Id = 1;
        MyHeader.MyHeaderProperty = "HeaderTest1";
        MyHeader.ChildOfHeader.Add(new ChildOfHeader());

        for (int i = 1; i <= 3; i++)
        {
            var childOfChild = new ChildOfChild()
            {
                Id = i,
                HeaderId = MyHeader.Id,
                MyChildProperty = $"FirstChildTest{i}"
            };

            MyHeader.ChildOfHeader[0].MyFirstChildList.Add(childOfChild);
        }

        for (int i = 1; i <= 2; i++)
        {
            var childOfChild = new ChildOfChild()
            {
                Id = i,
                HeaderId = MyHeader.Id,
                MyChildProperty = $"SecondChildTest{i}"
            };

            MyHeader.ChildOfHeader[0].MySecondChildList.Add(childOfChild);
        }

        if (HttpContext.Session.Get<Header>("HeaderData") == null)
        {
            HttpContext.Session.Set<Header>("HeaderData", MyHeader);
        }
    }

    public PartialViewResult OnPostAddNewFirstListChildItem([FromBody] Header myHeader)
    {
        if (myHeader.ChildOfHeader[0].MyFirstChildList == null)
            myHeader.ChildOfHeader[0].MyFirstChildList = new List<ChildOfChild>();

        var childId = myHeader.ChildOfHeader[0].MyFirstChildList.Count + 1;

        myHeader.ChildOfHeader[0].MyFirstChildList.Add(new ChildOfChild
        {
            Id = childId,
            HeaderId = myHeader.Id,
            MyChildProperty = $"FirstChildTest{childId}"
        });

        //var partialView = "_ListPartialView";
        var partialView = "_FirstListItemPartial";

        var data = new IndexModel(_logger);
        data.MyHeader = myHeader;

        var myViewData = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary()) { { partialView, myHeader } };
        //var myViewData = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary()) { { partialView, myHeader.ChildOfHeader[0].MyFirstChildList } };
        myViewData.Model = data;

        var partialViewResult = new PartialViewResult()
        {
            ViewName = partialView,
            ViewData = myViewData,
        };
        
        HttpContext.Session.Set<Header>("HeaderData", myHeader);

        return partialViewResult;
    }

    public PartialViewResult OnPostAddNewSecondListChildItem([FromBody] Header myHeader)
    {
        if (myHeader.ChildOfHeader[0].MySecondChildList == null)
            myHeader.ChildOfHeader[0].MySecondChildList = new List<ChildOfChild>();

        var childId = myHeader.ChildOfHeader[0].MySecondChildList.Count + 1;

        myHeader.ChildOfHeader[0].MySecondChildList.Add(new ChildOfChild
        {
            Id = childId,
            HeaderId = myHeader.Id,
            MyChildProperty = $"SecondChildTest{childId}"
        });

        //var partialView = "_ListPartialView";
        var partialView = "_SecondListItemPartial";

        var data = new IndexModel(_logger);
        data.MyHeader = myHeader;

        var myViewData = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary()) { { partialView, myHeader } };
        //var myViewData = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary()) { { partialView, myHeader.ChildOfHeader[0].MySecondChildList } };
        myViewData.Model = data;

        var partialViewResult = new PartialViewResult()
        {
            ViewName = partialView,
            ViewData = myViewData,
        };
        HttpContext.Session.Set<Header>("HeaderData", myHeader);
        return partialViewResult;
    }
    public JsonResult OnGetGetLatestData()
    {
        var result = new Header();
        if (HttpContext.Session.Get<Header>("HeaderData") != null)
        {
            result = HttpContext.Session.Get<Header>("HeaderData");
        };
        return new JsonResult(result);
    }

屏幕截图(更新):

要在 asp.net 核心应用程序中使用会话,请参阅Session and state management in ASP.NET Core

[注意]如果要使用会话存储复杂对象,则必须添加SessionExtensions。

【讨论】:

  • 非常感谢。我还有很多东西要学!直到明天我才能尝试它 - 它是否足够简单以更改真实列表的内容(不是橙色显示的位)?
  • 我已经按照您说明的方式工作了,但是现在我已经删除了橙色的 div(它只是在那里表明发生了一些事情),第一个列表和第二个列表没有增量。例如,如果我在_FirstListItemPartial 中放置一个断点,我可以看到它循环了正确的行数,但它不会输出所有tr。我不知道为什么。
  • @WayneReynolds,在 JavaScript AddListItem() 函数中,您必须将输出部分视图名称更改为子部分,如下所示:partialView = "#FirstListPartial";//"#ListPartialView"; 并在 OnPostAddNewFirstListChildItem() 和 OnPostAddNewSecondListChildItem 方法中,更改var partialView = "_ListPartialView";var partialView = "_FirstListItemPartial"var partialView = "_SecondListItemPartial";。我已经更新了回复中的代码和截图,请查收。
  • 感谢您的回复。您在 _FirstListItemPartial(和 _SecondListItemPartial)中做了什么吗?我的不起作用,因为 ViewData["ChildIndex"] 尚未通过 _ListPartialView 填充。我需要它通过 _ListPartialView 因为我使用这个 ViewData 在我的主应用程序中提供一些 div Id。
  • 是的,我在使用它之前检查它是否为空。像这样的代码:@{ var indexId = 0; if (ViewData["ChildIndex"] != null) { indexId = (int)ViewData["ChildIndex"]; }}
猜你喜欢
  • 2020-05-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-30
  • 2021-06-26
  • 2021-06-26
  • 2021-08-19
相关资源
最近更新 更多