ASP.NET Core 3.1 - 将子项添加到剃刀局部视图

Posted

技术标签:

【中文标题】ASP.NET Core 3.1 - 将子项添加到剃刀局部视图【英文标题】:ASP.NET Core 3.1 - adding child item to razor partial view 【发布时间】:2021-01-22 17:44:20 【问题描述】:

我是新手,我已经为此苦苦挣扎了好几天!

我想要做的只是将一个子项添加到父项,并刷新部分视图。 我的问题是当代码进入 OnGetAddNewChildItem 方法时,PageModel 类上的绑定属性为空(它不是 null,它只是没有数据)所以我无法添加孩子到这个。为了尝试解决这个问题,我尝试将数据传递到方法中,但这是 null。

奇怪的是,在我正在研究的实际解决方案中,我什至无法将它放入 PageModel 类,除非它是 PUT 或 POST - 但如果我能让这个演示工作,我敢肯定我将能够使主要解决方案正常工作。

我的 PageModel 类

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.MyChildPropertiesList.AddRange(
                new List<Child> 
                    new Child()  Id = 1, HeaderId = MyHeader.Id, MyChildProperty = "ChildTest1" ,
                    new Child()  Id = 2, HeaderId = MyHeader.Id, MyChildProperty = "ChildTest2" ,
                    new Child()  Id = 3, HeaderId = MyHeader.Id, MyChildProperty = "ChildTest3" 
                );
        

        public PartialViewResult OnGetAddNewChildItem([FromBody] Header myHeader)
        
            if (myHeader.MyChildPropertiesList == null)
                myHeader.MyChildPropertiesList = new List<Child>();

            myHeader.MyChildPropertiesList.Add(new Child
            
                Id = 4,
                HeaderId = myHeader.Id,
                MyChildProperty = "ChildTest4"
            );

            var partialView = "_ListItemPartial";

            var myViewData = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary())   partialView, myHeader.MyChildPropertiesList  ;
            myViewData.Model = myHeader;

            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<Child> MyChildPropertiesList  get; set;  = new List<Child>();
    

    public class Child
    
        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="AddItem()">Add Child Item</a>
</div>

<br />

<div>
    <div><b>MyHeaderProperty value:</b> @Model.MyHeader.MyHeaderProperty</div>
    <br />
    <div class="font-weight-bold">Child Items</div>
    <br />
    <div id="LineItemsPartial">
        <partial name="_ListItemPartial" model="@Model" />
    </div>

</div>

<script type="text/javascript">
    function AddItem() 
        var model = @Json.Serialize(Model.MyHeader);
        alert(JSON.stringify(model));
        $.ajax(
            type: "GET",
            url: "?handler=AddNewChildItem",
            data: JSON.stringify(model),
            dataType: "json",
            success: function (result) 
                alert("Success");
                $('#LineItemsPartial').html(result);
            ,
            failure: function (result) 
                alert("Failed");
            
        );
    
</script>

我的部分观点

@model IndexModel


<table>
    @foreach (var myChildItem in Model.MyHeader.MyChildPropertiesList)
    
        <tr>
            <td>@myChildItem.HeaderId</td>
            <td>@myChildItem.MyChildProperty</td>
        </tr>
    
</table>

非常感谢任何帮助。

【问题讨论】:

【参考方案1】:

从您的代码设计来看,您有以下一些错误:

1.在get方法中使用FromBody不是一个好方法。如果你想通过get请求向后端发送数据,你需要通过url中的查询字符串发送模型。你应该做的是一种 Post 请求方式。

参考:

https://***.com/a/983458/11398810

2.局部视图结果的ViewData是Header的类型。但是你的局部视图需要IndexModel的类型

这是一个工作演示:

Index.cshtml:

@page
@model IndexModel
<div>
    <a class="btn btn-sm btn-info text-white" onclick="AddItem()">Add Child Item</a>
</div>
<br />
<div>
    <div><b>MyHeaderProperty value:</b> @Model.MyHeader.MyHeaderProperty</div>
    <br />
    <div class="font-weight-bold">Child Items</div>
    <br />
    <div id="LineItemsPartial">
        <partial name="_ListItemPartial" model="@Model" />
    </div>
    @Html.AntiForgeryToken()  @*add this*@
</div>

<script type="text/javascript">
    function AddItem() 
        var model = @Json.Serialize(Model.MyHeader);
        $.ajax(
            type: "Post",      //change this...
            url: "?handler=AddNewChildItem",
            data: JSON.stringify(model),
            
            //add the following contentType and headers..
            contentType: "application/json",  
            headers: 
                RequestVerificationToken: $('input:hidden[name="__RequestVerificationToken"]').val()
            ,
            dataType: "html",     //midify this..
            success: function (result) 
                $('#LineItemsPartial').html(result);
            ,
            failure: function (result) 
                alert("Failed");
            
        );
    
</script>

索引.cshtml.cs:

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 PartialViewResult OnPostAddNewChildItem([FromBody] Header myHeader)
    
        if (myHeader.MyChildPropertiesList == null)
            myHeader.MyChildPropertiesList = new List<Child>();

        myHeader.MyChildPropertiesList.Add(new Child
        
            Id = 4,
            HeaderId = myHeader.Id,
            MyChildProperty = "ChildTest4"
        );

        //add this line....
        var data = new IndexModel(_logger);
        data.MyHeader = myHeader;

        var partialView = "_ListItemPartial";

        var myViewData = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary())   partialView, myHeader.MyChildPropertiesList  ;
        myViewData.Model = data;   //change here..

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

结果:

【讨论】:

完美。非常感谢。正是我需要的。

以上是关于ASP.NET Core 3.1 - 将子项添加到剃刀局部视图的主要内容,如果未能解决你的问题,请参考以下文章

使用 ADFS 的 JWT Bearer 身份验证将 ASP.NET Framework 迁移到 ASP.NET Core 3.1

将 Asp.Net Core 2.2 App 迁移到 3.1 时的整数序列化 [关闭]

ASP.NET Core 3.1 和 Angular:将 api 调用重定向到登录页面

将 JWT 自动加载到 User.Identity (ASP.NET Core 3.1)

如何将对象数组发送到服务器。 Asp.Net Core 3.1 405 方法不允许

使用 Asp.NET Core 3.1 框架将文件上传到服务器时如何使用 IFormFile 作为属性?