更新相关实体

时间:2018-11-19 17:52:40

标签: entity-framework asp.net-core partial-views razor-pages

AppUser身份模型:

public virtual ICollection<UserPhones> UserPhones { get; set; }

使用Razor Pages,我称为局部视图,如下所示:

@await Html.PartialAsync("_NameAndID", Model.AppUser)

PageModel:

[BindProperty]
public AppUser AppUser { get; set; }

 public IActionResult OnGet()
    {
        AppUser = _userManager.Users
                //.Include(x => x.UserAddresses) //OMITTED BC USING LAZY LOADING
                .SingleOrDefaultAsync(x => x.UserName == 
                     _httpContext.HttpContext.User.Identity.Name).Result;

        return Page();
    }

_NameAndID.cshtml中,我明确引用了UserPhones实体中的特定电话。使用:

<input type="hidden" asp-for="UserPhones
   .SingleOrDefault(z => z.Type == EnumPhoneType.Mobile).UserPhoneId" />

//other properties removed for brevity           

<div class="rvt-grid__item">
    <label asp-for="UserPhones.SingleOrDefault(z => z.Type == EnumPhoneType.Mobile).PhoneNumber">Mobile Phone</label>
    <input asp-for="UserPhones.SingleOrDefault(z => z.Type == EnumPhoneType.Mobile).PhoneNumber" autocomplete="tel" />
    <span asp-validation-for="UserPhones.SingleOrDefault(z => z.Type == EnumPhoneType.Mobile).PhoneNumber"></span>
</div>

在运行时,显式手机号码已正确加载。但是,当发布到public async Task<IActionResult> OnPostAsync()时,相关的AppUser.UserPhonesnull。 (问题

你能帮忙吗?

预先感谢您!!!!

1 个答案:

答案 0 :(得分:1)

原因

asp-for在这种情况下不能很好地工作。

考虑您在_NameAndID.cshtml中的代码:

<input asp-for="UserPhones.SingleOrDefault(z => z.Type == EnumPhoneType.Mobile).PhoneNumber" autocomplete="tel" />

请注意此处的LINQ扩展方法.SingleOrDefault(...)此处的asp-for不知道如何获取UserPhones.SingleOrDefault(z => z.Type == EnumPhoneType.Mobile).PhoneNumber的名称,因此它只是将其呈现为PhoneNumber 。结果,呈现的html将是:

<input autocomplete="tel" type="text" id="PhoneNumber" name="PhoneNumber" value="">

假设有人输入了911的值,当发布到服务器时,有效负载将是:

PhoneNumber=911

因为您在服务器端的页面模型是:

    [BindProperty]
    public AppUser AppUser{get;set;}

    public IActionResult OnGet()
    {
        // ...
    }

    public IActionResult OnPostAsync() 
    {
        return Page();
    }

请注意,AppUser.UserPhones属性是一个集合。换句话说,AppUser期望的有效载荷为:

UserPhones[0].UserPhoneId=1&UserPhones[0].PhoneNumber=911&UserPhones[1].UserPhoneId=2&UserPhones[1].PhoneNumber=119

但是,您发送到服务器的是:

PhoneNumber=911

因此,App.UserPhones将始终为空,而AppUser.PhoneNumber属性将为911

如何修复

首先,为了自动绑定UserPhones,我将App.UserPhones的类型更改为IList<UserPhones>,以便我们可以使用索引语法

public class AppUser : IdentityUser{

    // public virtual ICollection<UserPhones> UserPhones { get; set; }
    public virtual IList<UserPhones> UserPhones { get; set; }

}

第二,不要在asp-for中使用复杂的查询,而应使用简单的索引语法。例如,如果您想发布一些UserPhones或全部发布UserPhones,则可以为每个字段添加一个索引:

@for(var i=0;i <Model.UserPhones.Count(); i++) {

    <div class="rvt-grid__item">
        <label asp-for="@Model.UserPhones[i].UserPhoneId"></label>
        <input asp-for="@Model.UserPhones[i].UserPhoneId"/>
        <label asp-for="@Model.UserPhones[i].PhoneNumber"></label>
        <input asp-for="@Model.UserPhones[i].PhoneNumber"/>
        <span asp-validation-for="@Model.UserPhones[i].PhoneNumber"></span>
    </div>
}

这样,当有人提交表单时,AppUser.UserPhones将被正确设置。这是演示的屏幕截图:

enter image description here