I am pretty new with ASP.Net Core Razor pages and I would like your help on the following:
I have the following two classes:
public class Customer
{
[Key]
public int Id { get; set; }
[Required(ErrorMessage ="Please enter a name.")]
[Display(Name ="Customer Name")]
public string CustomerName { get; set; }
[Display(Name = "Customer Email")]
public string CustomerEmail { get; set; } = string.Empty;
[Display(Name ="Customer Phone Number")]
public string CustomerPhoneNumber { get; set; } = string.Empty;
public List<Invoice> Invoices { get; set; } = new();
}
and
public class Invoice
{
[Key]
public int Id { get; set; }
[Display(Name ="Invoice Number")]
public string InvNumber { get; set; }
[Display(Name = "Invoice Amount")]
public decimal InvAmount { get; set; }
[Display(Name = "Issued? (Yes/No)")]
public bool InvIssued { get; set; } = false;
[Display(Name = "Paid? (Yes/No)")]
public bool InvPaid { get; set; } = false;
public int CustomerId { get; set; }
}
The way I’ve set it up is for a one-to-many relationship. Now, two related issues are that during the Create form for an invoice I also need to input a CustomerID, otherwise I get an SQL exception error. However, for the life of me, I can’t figure out how to bind the data, to the Customer table, so that I can retrieve the list of available customers and have it as an option during the creation of an invoice.
My cshtml file contains:
<div class="form-group">
<label asp-for="Invoice.CustomerId" class="control-label"></label>
<input asp-for="Invoice.CustomerId" class="form-control" value="3"/>
<span asp-validation-for="Invoice.InvNumber" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Invoice.InvNumber" class="control-label"></label>
<input asp-for="Invoice.InvNumber" class="form-control" />
<span asp-validation-for="Invoice.InvNumber" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Invoice.InvAmount" class="control-label"></label>
<input asp-for="Invoice.InvAmount" class="form-control" />
<span asp-validation-for="Invoice.InvAmount" class="text-danger"></span>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="InvIssued" id="InvIssued" value="true" checked="">
<label class="form-check-label" asp-for="Invoice.InvIssued">
The invoice has been issued.
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="InvNotIssed" id="InvNotIssed" value="false">
<label class="form-check-label" asp-for="Invoice.InvIssued">
The invoice has not been issued.
</label>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
and my page model is:
public class AddInvoiceModel : PageModel
{
private readonly InvoicesAppContext InvoiceContext;
public AddInvoiceModel(InvoicesAppContext contextInvoices)
{
InvoiceContext = contextInvoices;
}
public IActionResult OnGet()
{
return Page();
}
[BindProperty]
public Invoice Invoice { get; set; }
// To protect from overposting attacks, see https://aka.ms/RazorPagesCRUD
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
InvoiceContext.Invoice.Add(Invoice);
await InvoiceContext.SaveChangesAsync();
return RedirectToPage("../Index");
}
}
So my questions are:
a) How do I add a reference to Customer table in the AddInvoice Page Model.
b) The CustomerID is an int and not the actual name of the customer. How do I retrieve the names and not the id?
Thank you all for your help. And sorry for this basic stuff. I am still learning.
3
Answers
Try this:
Link to source: https://www.learnrazorpages.com/razor-pages/model-binding
Usually, when creating an invoice, you know who the customer is, and therefore their ID. You assign this to the Invoice in
OnGet
:It’s then a question of adding that ID to the invoice form so that it is posted along with the rest of the invoice details. You’d add it to the form as a hidden field:
If you don’t know who the customer is, you provide a select list containing customers so that the user can select one for the invoice. You bind the select element to the
Invoice.CustomerId
property:The
CustomerOptions
is aSelectList
that you populate in theOnGet
handler:In the AddInvoiceModel:
In cshtml file:
result: