Updating related entities
up vote
1
down vote
favorite
AppUser identity model:
public virtual ICollection<UserPhones> UserPhones { get; set; }
Using Razor Pages, I call a partial view, like so:
@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();
}
Within _NameAndID.cshtml, I explicitly reference a particular telephone from the UserPhones entity. With:
<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>
At runtime, the explicit mobile phone number is loaded properly. However when posting to public async Task<IActionResult> OnPostAsync() the related AppUser.UserPhones is null. (The problem)
Can you help?
Thank you in advance!!!!
entity-framework asp.net-core partial-views razor-pages
add a comment |
up vote
1
down vote
favorite
AppUser identity model:
public virtual ICollection<UserPhones> UserPhones { get; set; }
Using Razor Pages, I call a partial view, like so:
@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();
}
Within _NameAndID.cshtml, I explicitly reference a particular telephone from the UserPhones entity. With:
<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>
At runtime, the explicit mobile phone number is loaded properly. However when posting to public async Task<IActionResult> OnPostAsync() the related AppUser.UserPhones is null. (The problem)
Can you help?
Thank you in advance!!!!
entity-framework asp.net-core partial-views razor-pages
add a comment |
up vote
1
down vote
favorite
up vote
1
down vote
favorite
AppUser identity model:
public virtual ICollection<UserPhones> UserPhones { get; set; }
Using Razor Pages, I call a partial view, like so:
@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();
}
Within _NameAndID.cshtml, I explicitly reference a particular telephone from the UserPhones entity. With:
<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>
At runtime, the explicit mobile phone number is loaded properly. However when posting to public async Task<IActionResult> OnPostAsync() the related AppUser.UserPhones is null. (The problem)
Can you help?
Thank you in advance!!!!
entity-framework asp.net-core partial-views razor-pages
AppUser identity model:
public virtual ICollection<UserPhones> UserPhones { get; set; }
Using Razor Pages, I call a partial view, like so:
@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();
}
Within _NameAndID.cshtml, I explicitly reference a particular telephone from the UserPhones entity. With:
<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>
At runtime, the explicit mobile phone number is loaded properly. However when posting to public async Task<IActionResult> OnPostAsync() the related AppUser.UserPhones is null. (The problem)
Can you help?
Thank you in advance!!!!
entity-framework asp.net-core partial-views razor-pages
entity-framework asp.net-core partial-views razor-pages
asked Nov 19 at 17:52
Fraze
145313
145313
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
up vote
1
down vote
accepted
The Reason
The asp-for does not work well for this scenario.
Considering your code in _NameAndID.cshtml :
<input asp-for="UserPhones.SingleOrDefault(z => z.Type == EnumPhoneType.Mobile).PhoneNumber" autocomplete="tel" />
Note the LINQ extension method .SingleOrDefault(...) here. The asp-for here does not know how to get the name for UserPhones.SingleOrDefault(z => z.Type == EnumPhoneType.Mobile).PhoneNumber, so it just render it as PhoneNumber. As a result, the rendered html will be :
<input autocomplete="tel" type="text" id="PhoneNumber" name="PhoneNumber" value="">
Let's say someone inputs an value of 911, when posted to server, the payload will be :
PhoneNumber=911
As your page model on server side is :
[BindProperty]
public AppUser AppUser{get;set;}
public IActionResult OnGet()
{
// ...
}
public IActionResult OnPostAsync()
{
return Page();
}
Note the AppUser.UserPhones property is a collection. in other words, AppUser expects a payload like :
UserPhones[0].UserPhoneId=1&UserPhones[0].PhoneNumber=911&UserPhones[1].UserPhoneId=2&UserPhones[1].PhoneNumber=119
However, what you send to the server is :
PhoneNumber=911
So the App.UserPhones will always be null and the AppUser.PhoneNumber property will be 911.
How to Fix
Firstly, in order to bind the UserPhones automatically, I change the type of App.UserPhones to IList<UserPhones> , so that we can use a index syntax
public class AppUser : IdentityUser{
// public virtual ICollection<UserPhones> UserPhones { get; set; }
public virtual IList<UserPhones> UserPhones { get; set; }
}
Secondly, don't use complex query in asp-for, use simple index syntax instead. For example, if you would like to post some UserPhones or post all UserPhones, you can add an index for each field :
@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>
}
In this way, when someone submits the form, AppUser.UserPhones will be the correctly set. Here's a screenshot of demo :

Thank you @itminus! This is exactly what I ended up doing yesterday and it worked like a champ. Considering converting to a tag helper though so that I can make it reusable throughout the application where the phone number needs edited. Thanks again!
– Fraze
Nov 20 at 12:26
Hi again @itminus, I posted a the custom tag helper idea if you are interested in helping with that as well. No worries if not. Thanks again. See: stackoverflow.com/questions/53395905/complex-custom-tag-helper
– Fraze
Nov 20 at 15:07
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1
down vote
accepted
The Reason
The asp-for does not work well for this scenario.
Considering your code in _NameAndID.cshtml :
<input asp-for="UserPhones.SingleOrDefault(z => z.Type == EnumPhoneType.Mobile).PhoneNumber" autocomplete="tel" />
Note the LINQ extension method .SingleOrDefault(...) here. The asp-for here does not know how to get the name for UserPhones.SingleOrDefault(z => z.Type == EnumPhoneType.Mobile).PhoneNumber, so it just render it as PhoneNumber. As a result, the rendered html will be :
<input autocomplete="tel" type="text" id="PhoneNumber" name="PhoneNumber" value="">
Let's say someone inputs an value of 911, when posted to server, the payload will be :
PhoneNumber=911
As your page model on server side is :
[BindProperty]
public AppUser AppUser{get;set;}
public IActionResult OnGet()
{
// ...
}
public IActionResult OnPostAsync()
{
return Page();
}
Note the AppUser.UserPhones property is a collection. in other words, AppUser expects a payload like :
UserPhones[0].UserPhoneId=1&UserPhones[0].PhoneNumber=911&UserPhones[1].UserPhoneId=2&UserPhones[1].PhoneNumber=119
However, what you send to the server is :
PhoneNumber=911
So the App.UserPhones will always be null and the AppUser.PhoneNumber property will be 911.
How to Fix
Firstly, in order to bind the UserPhones automatically, I change the type of App.UserPhones to IList<UserPhones> , so that we can use a index syntax
public class AppUser : IdentityUser{
// public virtual ICollection<UserPhones> UserPhones { get; set; }
public virtual IList<UserPhones> UserPhones { get; set; }
}
Secondly, don't use complex query in asp-for, use simple index syntax instead. For example, if you would like to post some UserPhones or post all UserPhones, you can add an index for each field :
@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>
}
In this way, when someone submits the form, AppUser.UserPhones will be the correctly set. Here's a screenshot of demo :

Thank you @itminus! This is exactly what I ended up doing yesterday and it worked like a champ. Considering converting to a tag helper though so that I can make it reusable throughout the application where the phone number needs edited. Thanks again!
– Fraze
Nov 20 at 12:26
Hi again @itminus, I posted a the custom tag helper idea if you are interested in helping with that as well. No worries if not. Thanks again. See: stackoverflow.com/questions/53395905/complex-custom-tag-helper
– Fraze
Nov 20 at 15:07
add a comment |
up vote
1
down vote
accepted
The Reason
The asp-for does not work well for this scenario.
Considering your code in _NameAndID.cshtml :
<input asp-for="UserPhones.SingleOrDefault(z => z.Type == EnumPhoneType.Mobile).PhoneNumber" autocomplete="tel" />
Note the LINQ extension method .SingleOrDefault(...) here. The asp-for here does not know how to get the name for UserPhones.SingleOrDefault(z => z.Type == EnumPhoneType.Mobile).PhoneNumber, so it just render it as PhoneNumber. As a result, the rendered html will be :
<input autocomplete="tel" type="text" id="PhoneNumber" name="PhoneNumber" value="">
Let's say someone inputs an value of 911, when posted to server, the payload will be :
PhoneNumber=911
As your page model on server side is :
[BindProperty]
public AppUser AppUser{get;set;}
public IActionResult OnGet()
{
// ...
}
public IActionResult OnPostAsync()
{
return Page();
}
Note the AppUser.UserPhones property is a collection. in other words, AppUser expects a payload like :
UserPhones[0].UserPhoneId=1&UserPhones[0].PhoneNumber=911&UserPhones[1].UserPhoneId=2&UserPhones[1].PhoneNumber=119
However, what you send to the server is :
PhoneNumber=911
So the App.UserPhones will always be null and the AppUser.PhoneNumber property will be 911.
How to Fix
Firstly, in order to bind the UserPhones automatically, I change the type of App.UserPhones to IList<UserPhones> , so that we can use a index syntax
public class AppUser : IdentityUser{
// public virtual ICollection<UserPhones> UserPhones { get; set; }
public virtual IList<UserPhones> UserPhones { get; set; }
}
Secondly, don't use complex query in asp-for, use simple index syntax instead. For example, if you would like to post some UserPhones or post all UserPhones, you can add an index for each field :
@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>
}
In this way, when someone submits the form, AppUser.UserPhones will be the correctly set. Here's a screenshot of demo :

Thank you @itminus! This is exactly what I ended up doing yesterday and it worked like a champ. Considering converting to a tag helper though so that I can make it reusable throughout the application where the phone number needs edited. Thanks again!
– Fraze
Nov 20 at 12:26
Hi again @itminus, I posted a the custom tag helper idea if you are interested in helping with that as well. No worries if not. Thanks again. See: stackoverflow.com/questions/53395905/complex-custom-tag-helper
– Fraze
Nov 20 at 15:07
add a comment |
up vote
1
down vote
accepted
up vote
1
down vote
accepted
The Reason
The asp-for does not work well for this scenario.
Considering your code in _NameAndID.cshtml :
<input asp-for="UserPhones.SingleOrDefault(z => z.Type == EnumPhoneType.Mobile).PhoneNumber" autocomplete="tel" />
Note the LINQ extension method .SingleOrDefault(...) here. The asp-for here does not know how to get the name for UserPhones.SingleOrDefault(z => z.Type == EnumPhoneType.Mobile).PhoneNumber, so it just render it as PhoneNumber. As a result, the rendered html will be :
<input autocomplete="tel" type="text" id="PhoneNumber" name="PhoneNumber" value="">
Let's say someone inputs an value of 911, when posted to server, the payload will be :
PhoneNumber=911
As your page model on server side is :
[BindProperty]
public AppUser AppUser{get;set;}
public IActionResult OnGet()
{
// ...
}
public IActionResult OnPostAsync()
{
return Page();
}
Note the AppUser.UserPhones property is a collection. in other words, AppUser expects a payload like :
UserPhones[0].UserPhoneId=1&UserPhones[0].PhoneNumber=911&UserPhones[1].UserPhoneId=2&UserPhones[1].PhoneNumber=119
However, what you send to the server is :
PhoneNumber=911
So the App.UserPhones will always be null and the AppUser.PhoneNumber property will be 911.
How to Fix
Firstly, in order to bind the UserPhones automatically, I change the type of App.UserPhones to IList<UserPhones> , so that we can use a index syntax
public class AppUser : IdentityUser{
// public virtual ICollection<UserPhones> UserPhones { get; set; }
public virtual IList<UserPhones> UserPhones { get; set; }
}
Secondly, don't use complex query in asp-for, use simple index syntax instead. For example, if you would like to post some UserPhones or post all UserPhones, you can add an index for each field :
@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>
}
In this way, when someone submits the form, AppUser.UserPhones will be the correctly set. Here's a screenshot of demo :

The Reason
The asp-for does not work well for this scenario.
Considering your code in _NameAndID.cshtml :
<input asp-for="UserPhones.SingleOrDefault(z => z.Type == EnumPhoneType.Mobile).PhoneNumber" autocomplete="tel" />
Note the LINQ extension method .SingleOrDefault(...) here. The asp-for here does not know how to get the name for UserPhones.SingleOrDefault(z => z.Type == EnumPhoneType.Mobile).PhoneNumber, so it just render it as PhoneNumber. As a result, the rendered html will be :
<input autocomplete="tel" type="text" id="PhoneNumber" name="PhoneNumber" value="">
Let's say someone inputs an value of 911, when posted to server, the payload will be :
PhoneNumber=911
As your page model on server side is :
[BindProperty]
public AppUser AppUser{get;set;}
public IActionResult OnGet()
{
// ...
}
public IActionResult OnPostAsync()
{
return Page();
}
Note the AppUser.UserPhones property is a collection. in other words, AppUser expects a payload like :
UserPhones[0].UserPhoneId=1&UserPhones[0].PhoneNumber=911&UserPhones[1].UserPhoneId=2&UserPhones[1].PhoneNumber=119
However, what you send to the server is :
PhoneNumber=911
So the App.UserPhones will always be null and the AppUser.PhoneNumber property will be 911.
How to Fix
Firstly, in order to bind the UserPhones automatically, I change the type of App.UserPhones to IList<UserPhones> , so that we can use a index syntax
public class AppUser : IdentityUser{
// public virtual ICollection<UserPhones> UserPhones { get; set; }
public virtual IList<UserPhones> UserPhones { get; set; }
}
Secondly, don't use complex query in asp-for, use simple index syntax instead. For example, if you would like to post some UserPhones or post all UserPhones, you can add an index for each field :
@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>
}
In this way, when someone submits the form, AppUser.UserPhones will be the correctly set. Here's a screenshot of demo :

answered Nov 20 at 8:36
itminus
2,4311318
2,4311318
Thank you @itminus! This is exactly what I ended up doing yesterday and it worked like a champ. Considering converting to a tag helper though so that I can make it reusable throughout the application where the phone number needs edited. Thanks again!
– Fraze
Nov 20 at 12:26
Hi again @itminus, I posted a the custom tag helper idea if you are interested in helping with that as well. No worries if not. Thanks again. See: stackoverflow.com/questions/53395905/complex-custom-tag-helper
– Fraze
Nov 20 at 15:07
add a comment |
Thank you @itminus! This is exactly what I ended up doing yesterday and it worked like a champ. Considering converting to a tag helper though so that I can make it reusable throughout the application where the phone number needs edited. Thanks again!
– Fraze
Nov 20 at 12:26
Hi again @itminus, I posted a the custom tag helper idea if you are interested in helping with that as well. No worries if not. Thanks again. See: stackoverflow.com/questions/53395905/complex-custom-tag-helper
– Fraze
Nov 20 at 15:07
Thank you @itminus! This is exactly what I ended up doing yesterday and it worked like a champ. Considering converting to a tag helper though so that I can make it reusable throughout the application where the phone number needs edited. Thanks again!
– Fraze
Nov 20 at 12:26
Thank you @itminus! This is exactly what I ended up doing yesterday and it worked like a champ. Considering converting to a tag helper though so that I can make it reusable throughout the application where the phone number needs edited. Thanks again!
– Fraze
Nov 20 at 12:26
Hi again @itminus, I posted a the custom tag helper idea if you are interested in helping with that as well. No worries if not. Thanks again. See: stackoverflow.com/questions/53395905/complex-custom-tag-helper
– Fraze
Nov 20 at 15:07
Hi again @itminus, I posted a the custom tag helper idea if you are interested in helping with that as well. No worries if not. Thanks again. See: stackoverflow.com/questions/53395905/complex-custom-tag-helper
– Fraze
Nov 20 at 15:07
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53380176%2fupdating-related-entities%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown