I have a question about model binding in ASP.NET Core Razor pages. I've spent a lot of time reading the Microsoft documentation, Stackoverflow posts and learnrazorpages.com, but haven't quite found the answer I'm looking for. So below is a stripped down version of three classes I have. As you can see, both Client and ReferralPerson contain Person objects and Client also contains a ReferralPerson object. On my razor page (the data entry form), I intentionally do not show all of the fields for the Person object that is part of the ReferralPerson. There are also other properties of the ReferralPerson object that are not shown such as NumberOfReferrals. If a user recalls a record, modifies some of the data and then saves (Post), only those properties that I have included inside of the element end up being populated in the model in the OnPost (OnPostSave). I understand why this is. My question is do I have to include every single property, individually on the page in order for those properties to be populated in the OnPost event? If you look at my Razor page code below, you will see that I add a number of hidden fields at the top of the element. Do I need to do that for every single property that isn't visible or included somewhere else inside that form? Ideally I would just be able to do something like the following to include the entire object versus having hidden fields for every single property. I just want to make sure there isn't something I'm not aware of in terms of how this can or should be handled.
<input type="hidden" asp-for="Client.ReferralPerson" />
Here are the C# classes (model)
public class Person
{
public int ID { get; set; }
[Required, StringLength(50)]
public string FirstName { get; set; } = "N/A";
[Required, StringLength(50)]
public string LastName { get; set; } = "N/A";
[StringLength(30)]
public string PhoneNumberPrimary { get; set; }
[StringLength(30)]
public string PhoneNumberSecondary { get; set; }
[StringLength(50)]
public string Address { get; set; }
[StringLength(50)]
public string EmailAddress { get; set; }
}
public class Client
{
public int ID { get; set; }
public Person Person { get; set; }
public DateTime InitalContactDate { get; set; }
[Required, StringLength(100)]
public string ReasonForVisit { get; set; }
public ReferralPerson ReferralPerson { get; set; }
//other properties removed for brevity
}
public class ReferralPerson
{
public int ID { get; set; }
public Person Person { get; set; }
[StringLength(100)]
public string BusinessName { get; set; }
public int NumberOfReferrals { get; set; }
}
Here's a simplified version of my Razor page:
<form novalidate="" method="post">
<input type="hidden" asp-for="Client.ID" />
<input type="hidden" asp-for="Client.Person.ID" />
<input type="hidden" asp-for="Client.ContactType.ID" />
<input type="hidden" asp-for="Client.ReferralPerson.ID" />
<input type="hidden" asp-for="Client.ReferralPerson.Person.ID" />
<div >
<div >
<label asp-for="Client.Person.FirstName" >First name</label>
<input type="text" asp-for="Client.Person.FirstName">
<span asp-validation-for="Client.Person.FirstName" ></span>
</div>
<div >
<label asp-for="Client.Person.LastName" >Last name</label>
<input type="text" asp-for="Client.Person.LastName">
<span asp-validation-for="Client.Person.LastName" ></span>
</div>
</div>
<div >
<div >
<label for="type" >Date</label>
<input type="date" asp-for="Client.InitalContactDate">
<span asp-validation-for="Client.InitalContactDate" ></span>
</div>
<div >
<label for="email" >Email <span >(Optional)</span></label>
<input type="email" placeholder="[email protected]" asp-for="Client.Person.EmailAddress">
</div>
</div>
<div >
<div >
<label for="primaryPhone" >Phone # (Primary)</label>
<input type="text" placeholder="Phone Number" asp-for="Client.Person.PhoneNumberPrimary">
</div>
<div >
<label for="secodaryPhone" >Phone # (Secondary)</label>
<input type="text" placeholder="Phone Number" asp-for="Client.Person.PhoneNumberSecondary">
</div>
</div>
<div >
<div >
<label for="address" >Address</label>
<input type="text" placeholder="1234 Main St" asp-for="Client.Person.Address">
</div>
</div>
<div id="ReferralPersonDetails" style="display:none">
<div >
<label asp-for="Client.ReferralPerson.Person.FirstName" >Referral By First name</label>
<input type="text" asp-for="Client.ReferralPerson.Person.FirstName">
</div>
<div >
<label asp-for="Client.ReferralPerson.Person.LastName" >Referral By Last name</label>
<input type="text" asp-for="Client.ReferralPerson.Person.LastName">
</div>
</div>
<hr >
<div >
<hr >
<button type="submit" asp-page-handler="Save">Save</button>
</div>
</form>
CodePudding user response:
You don't need to do the same with all id fields. I guess you are trying to edit the information of Client and ReferralPerson, adding the .Person.ID fields is not necessary because surely your database already has information about Person in each Client or ReferralPerson, get it out in controller process this action then edit it with data from the form.
CodePudding user response:
Model binding
is based on the name of properties in model, If you don't use
<input asp-for="xxx">
to bind the specified property, After submitting the form, These properties will not be populated in post method. So if you don't bind all properties, those that are not bound will not be populated in the post method.
But in your data form, I think you just want to let the user modify some properties. So in my opinion, You can create a viewmodel
to include the properties whitch you want to change, In this method you don't need to bind all the properties in the form. Then in your controller, You just need to replace the original data with the data in the viewmodel
.