skip to Main Content

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


  1. Try this:

    public class Order
    {
        public int OrderId { get; set; }
        public string Customer { get; set; }
        public List<OrderItem> OrderItems { get; set; }
    }
    public class OrderItem
    {
        public int OrderItemId { get; set; }
        public string Item { get; set; }
        public decimal Price { get; set; }
    }
    
    @page
    @model CreateModel
    @{
    }
    <form method="post">
        <input asp-for="Order.Customer" /><br />
        <input asp-for="Order.OrderItems[0].Item" /><br>
        <input asp-for="Order.OrderItems[0].Price" /><br>
        <input type="submit"/>
    </form>
    
        public class CreateModel : PageModel
    {
        [BindProperty]
        public Order Order { get; set; }
        public void OnPost()
        {
        }
    }
    

    Link to source: https://www.learnrazorpages.com/razor-pages/model-binding

    Login or Signup to reply.
  2. Usually, when creating an invoice, you know who the customer is, and therefore their ID. You assign this to the Invoice in OnGet:

    public IActionResult OnGet()
    {
        Invoice = new Invoice{ CustomerId = id };
        return Page();
    }
    

    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:

    <input asp-for="Invoice.CustomerId" type="hidden" />
    

    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:

    <select asp-for="Invoice.CustomerId" asp-items="Model.CustomerOptions"></select>
    

    The CustomerOptions is a SelectList that you populate in the OnGet handler:

    public SelectList CustomerOptions { get; set; }
    public async Task<IActionResult> OnGet()
    {
        CustomerOptions = new SelectList(await db.Customers.Select(x => new SelectListItem{
            Value = x.CustomerId.ToString(),
            Text = x.CustomerName
        }).ToListAsync(), nameof(SelectListItem.Value), nameof(SelectListItem.Text));
        return Page();
    }
    
    Login or Signup to reply.
  3. In the AddInvoiceModel:

     public class AddInvoiceModel : PageModel
        {
           private readonly InvoicesAppContext InvoiceContext;
    
           public AddInvoiceModel(InvoicesAppContext contextInvoices)
             {
               InvoiceContext = contextInvoices;
             }
    
            public SelectList CustomerOptions { get; set; }
            public IActionResult OnGet()
            {
                List<Customer> cities = new()
                {
                    new Customer { Id = 1, CustomerName = "Latur" },
                    new Customer { Id = 2, CustomerName = "Solapur" },
                   
                };// you also can get data from database
                CustomerOptions = new SelectList(cities.Select(x => new SelectListItem
                {
                    Value = x.Id.ToString(),
                    Text = x.CustomerName
                }).ToList(), "Value", "Text");
                return Page();
            }
    

    In cshtml file:

           <div class="form-group">
                <label asp-for="Invoice.CustomerId" class="control-label"></label>
               <select asp-for="Invoice.CustomerId" class="form-control" asp-items="Model.CustomerOptions"></select>
                <span asp-validation-for="Invoice.CustomerId" class="text-danger"></span>
            </div>
    

    result:

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search