繁体   English   中英

ASP.NET Core 3.1 Razor 页面 - 向标题添加不同的子对象

[英]ASP.NET Core 3.1 Razor pages - adding different child objects to header

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

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

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

为了尝试查看发生了什么,我添加了一个部分来显示 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>

任何帮助,将不胜感激。

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

如果在 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 Core应用程序中使用会话,请参阅ASP.NET Core 中的会话和状态管理

【注意】如果要使用session来存储复杂的对象,必须添加SessionExtensions。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM