Search code examples
c#razorasp.net-core-mvc.net-8.0

Passing ID through asp-route


I'm working with an ASP.NET Core 8 MVC project where I have two simple tables that populate products and clients respectively. When clicking to view or edit an entity (doesn't matter which at this point), it should populate the page with the product or client info, however, I get a null reference.

I have debugged the issue and it appears that when I make a call to the views page detail the ID being passed is 0. Why is that if it can get the products and/or clients and display them for the two tables? Also I'm passing the id's through asp-route-id.

Dashboard.cshtml:

<div class="row">
    <h2>Products</h2>
    <table class="table table-striped">
        <thead>
            <tr>
                <th scope="col">#</th>
                <th scope="col">Product Name</th>
                <th scope="col">Part Number</th>
                <th scope="col">UPC</th>
                <th scope="col">Price</th>
                <th scope="col">Actions</th>
            </tr>
        </thead>
        <tbody>
            @foreach(var product in @ViewBag.Products)
            {
                <tr>
                    <td>@product.Id</td>
                    <td>@product.ProductName</td>
                    <td>@product.PartNumber</td>
                    <td>@product.UPC</td>
                    <td>[email protected]</td>
                    <td>
                        <a class="btn btn-primary" asp-area="" asp-controller="Admin" asp-action="ViewProductDetails" asp-route-id="@product.Id">View</a>
                        <a class="btn btn-primary" asp-area="" asp-controller="Admin" asp-action="UpdateProduct" asp-route-id="@product.Id">Update</a>
                    </td>
                </tr>
            }
        </tbody>
    </table>
</div>
<div class="row">
    <h2>Clients</h2>
    <table class="table table-striped">
        <thead>
            <tr>
                <th scope="col">#</th>
                <th scope="col">Address</th>
                <th scope="col">Phone Number</th>
                <th scope="col">Actions</th>
            </tr>
        </thead>
        <tbody>
            @foreach(var client in @ViewBag.Clients)
            {
                <tr>
                    <td>@client.Id</td>
                    <td>@client.Address</td>
                    <td>@client.PhoneNumber</td>
                    <td>
                        <a class="btn btn-primary" asp-area="" asp-controller="Admin" asp-action="ViewClientDetails" asp-route-id="@client.Id">View</a>
                        <a class="btn btn-primary" asp-area="" asp-controller="Admin" asp-action="UpdateClient" asp-route-id="@client.Id">Update</a>
                    </td>
                </tr>
            }
        </tbody>
    </table>
</div>

AdminController:

public async Task<IActionResult> Dashboard()
{
    List<Client> clients = await _dbContext.Clients.OrderBy(client => client.Id).ToListAsync();
    List<Product> products = await _dbContext.Products.OrderBy(products => products.Id).ToListAsync();
    // Gets both Lists just fine and displays them
    ViewBag.Clients = clients;
    ViewBag.Products = products;
    return View();
}

// Other code
// These methods are doing the same behavior. int of either productId or clientId are 0
// It shouldn't be 0

public async Task<IActionResult> UpdateProduct(int productId)
{
    Product prod = await _dbContext.Products.FirstOrDefaultAsync(product => product.Id == productId);
    return View(prod);
}

public async Task<IActionResult> ViewProductDetails(int productId)
{
    Product prod = await _dbContext.Products.FirstOrDefaultAsync(product => product.Id == productId);
    return View(prod);
}

public async Task<IActionResult> UpdateClient(int clientId)
{
    Client client = await _dbContext.Clients.FirstOrDefaultAsync(client => client.Id == clientId);
    return View(client);
}

public async Task<IActionResult> ViewClientDetails(int clientId)
{
    Client client = await _dbContext.Clients.FindAsync(clientId);
    return View(client);
}

Solution

  • when I make a call to the views page detail the ID being passed is 0. Why is that if it can get the products and/or clients and display them for the two tables?

    You pass value through route data by using asp-route-{value} attribute, use asp-route-id="@product.Id" in tag helper, please make sure your action parameter name match with that route parameter name.

    To fix issue, you can modify the action parameter like below.

    public async Task<IActionResult> ViewProductDetails(int id)
    {
        //...
    

    Test Result

    enter image description here