Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do routing with parameters in ASP.NET Core 3.1

In ASP.NET Core 3.1, when I specify the route in controller, must be kind of

[Route("/[area]/[controller]/[action]/{id}")]

but when it's like

[Route("/[area]/[controller]/[action]?id={id}")]

it returns an error 500.

I want to show a TableData from JS in the route

 Admin/Order/Index?status={status}

but, in the controller, the HttpGet is the action GetOrderList so data is sent to

Admin/Order/GetOrderList?status={status}

How could I configure the route right?

Controller:

[Area("Admin")]
[ApiController]
[Route("Admin/Order/")]
[Authorize]
public class OrderController : Controller
{
    #region Properties
    private readonly IUnitOfWork _unitOfWork;

    private Claim _claim
    {
        get
        {
            ClaimsIdentity claimsIdentity = (ClaimsIdentity)User.Identity;
            return claimsIdentity.FindFirst(ClaimTypes.NameIdentifier);
        }
        set { }
    }
    #endregion

    public OrderController(IUnitOfWork unitOfWork)
    {
        _unitOfWork = unitOfWork;
    }

    [Route("Index")]
    public IActionResult Index()
    {
        return View();
    }

    #region API CALLS

    [Route("GetOrderList")]
    [HttpGet]
    public IActionResult GetOrderList(string status)
    {
        IEnumerable<OrderHeader> orderHeaderList;
        // Repetimos codigo del switch, para que la recogida de datos sea más eficiente.
        // Si hicieramos switch al final, y aplicamos filtro al IEnumerable<T>, estamos leyendo
        // Todos los datos, y despues aplicamos filtro
        // Mientras que si aplicamos el filtro en el GetAll() hacemos uso del IQueryable<T> que
        // Aplica el filtro en la base de datos, y carga en memoria lo necesario

        if(User.IsInRole(SD.Role_Admin) || User.IsInRole(SD.Role_Employee))
        {
            // Si es admin, puede gestionar todas las transacciones
            switch (status)
            {
                case "pending":
                    orderHeaderList = _unitOfWork.OrderHeader.GetAll(item => item.PaymentStatus == SD.PaymentStatusDelayedPayment,
                                                                     includeProperties: "ApplicationUser");
                    break;
                case "inprocess":
                    orderHeaderList = _unitOfWork.OrderHeader.GetAll(item => item.OrderStatus == SD.StatusApproved ||
                                                                     item.OrderStatus == SD.StatusInProcess ||
                                                                     item.OrderStatus == SD.StatusPending,
                                                                     includeProperties: "ApplicationUser");
                    break;
                case "completed":
                    orderHeaderList = _unitOfWork.OrderHeader.GetAll(item => item.OrderStatus == SD.StatusShipped,
                                                                     includeProperties: "ApplicationUser");
                    break;
                case "rejected":
                    orderHeaderList = _unitOfWork.OrderHeader.GetAll(item => item.OrderStatus == SD.StatusCancelled ||
                                                                     item.OrderStatus == SD.StatusRefunded,
                                                                     includeProperties: "ApplicationUser");
                    break;
                case "approved":
                    orderHeaderList = _unitOfWork.OrderHeader.GetAll(item => item.OrderStatus == SD.PaymentStatusApproved ||
                                                                     item.OrderStatus == SD.StatusApproved,
                                                                     includeProperties: "ApplicationUser");
                    break;
                default:
                    orderHeaderList = _unitOfWork.OrderHeader.GetAll(includeProperties: "ApplicationUser");
                    break;
            };
        }
        else
        {
            // Si es trabajador, solo puede acceder a las suyas
            switch (status)
            {
                case "pending":
                    orderHeaderList = _unitOfWork.OrderHeader.GetAll(item => item.ApplicationUserId == _claim.Value &&
                                                                     (item.PaymentStatus == SD.PaymentStatusDelayedPayment), includeProperties: "ApplicationUser");
                    break;
                case "approved":
                    orderHeaderList = _unitOfWork.OrderHeader.GetAll(item => item.ApplicationUserId == _claim.Value &&
                                                                     (item.OrderStatus == SD.PaymentStatusApproved ||
                                                                     item.OrderStatus == SD.StatusApproved), includeProperties: "ApplicationUser");
                    break;
                case "inprocess":
                    orderHeaderList = _unitOfWork.OrderHeader.GetAll(item => item.ApplicationUserId == _claim.Value &&
                                                                     (item.OrderStatus == SD.StatusApproved ||
                                                                     item.OrderStatus == SD.StatusInProcess ||
                                                                     item.OrderStatus == SD.StatusPending), includeProperties: "ApplicationUser");
                    break;
                case "completed":
                    orderHeaderList = _unitOfWork.OrderHeader.GetAll(item => item.ApplicationUserId == _claim.Value &&
                                                                     (item.OrderStatus == SD.StatusShipped), includeProperties: "ApplicationUser");
                    break;
                case "rejected":
                    orderHeaderList = _unitOfWork.OrderHeader.GetAll(item => item.ApplicationUserId == _claim.Value &&
                                                                     (item.OrderStatus == SD.StatusCancelled ||
                                                                     item.OrderStatus == SD.StatusRefunded), includeProperties: "ApplicationUser");
                    break;
                default:
                    orderHeaderList = _unitOfWork.OrderHeader.GetAll(item => item.ApplicationUserId == _claim.Value, includeProperties: "ApplicationUser");
                    break;
            };

        }

        return Json(new { data = orderHeaderList });
    }

    #endregion
}

Index View:

@{
    Layout = "~/Views/Shared/_Layout.cshtml";

    var status = Context.Request.Query["status"];
    var approved = "text-primary";
    var pending = "text-primary";
    var all = "text-primary";
    var inprocess = "text-primary";
    var completed = "text-primary";
    var rejected = "text-primary";

    switch (status)
    {
        case "pending":
            pending = "active text-white";
            break;
        case "approved":
            approved = "active text-white";
            break;
        case "inprocess":
            inprocess = "active text-white";
            break;
        case "completed":
            completed = "active text-white";
            break;
        case "rejected":
            rejected = "active text-white";
            break;
        default:
            all = "active text-white";
            break;
    };
}

<br />

<div class="border p-3">
    <div class=" d-flex justify-content-between mb-3">
        <div class="p-2">
            <h2 class="text-primary">Order's List </h2>
        </div>
        <div class="p-2">
            <ul class="list-group list-group-horizontal-sm">
                <a style="text-decoration:none;" asp-controller="Order" asp-action="Index" asp-route-status="inprocess">
                    <li class="list-group-item @inprocess"> In Process</li>
                </a>
                <a style="text-decoration:none;" asp-controller="Order" asp-action="Index" asp-route-status="pending">
                    <li class="list-group-item @pending">Pending</li>
                </a>

                <a style="text-decoration:none;" asp-controller="Order" asp-action="Index" asp-route-status="completed">
                    <li class="list-group-item @completed">Completed</li>
                </a>

                <a style="text-decoration:none;" asp-controller="Order" asp-action="Index" asp-route-status="approved">
                    <li class="list-group-item @approved">Approved</li>
                </a>

                <a style="text-decoration:none;" asp-controller="Order" asp-action="Index" asp-route-status="rejected">
                    <li class="list-group-item @rejected">Rejected</li>
                </a>

                <a style="text-decoration:none;" asp-controller="Order" asp-action="Index" asp-route-status="all">
                    <li class="list-group-item @all">All</li>
                </a>
            </ul>
        </div>
    </div>

    <br /><br />

    <table id="tblData" class="table table-striped table-bordered" style="width:100%">
        <thead class="thead-dark">
            <tr class="table-info">
                <th>Id</th>
                <th>Name</th>
                <th>Phone number</th>
                <th>Email</th>
                <th>Order status</th>
                <th>Amount</th>
            </tr>
        </thead>
    </table>
</div>



@section Scripts {
    <script src ="~/js/order.js"></script>
}

order.js

var dataTable;

$(document).ready(function () {
    var url = window.location.search;
    if (url.includes("inprocess")) {
        loadDataTable("GetOrderList?status=inprocess");
    } else {
        if (url.includes("pending")) {
            loadDataTable("GetOrderList/status=pending");
        } else {
            if (url.includes("completed")) {
                loadDataTable("GetOrderList?status=completed");
            } else {
                if (url.includes("rejected")) {
                    loadDataTable("GetOrderList?status=rejected");
                } else {
                    loadDataTable("GetOrderList?status=all")
                }
            }
        }
    }

});

function loadDataTable(url) {
    dataTable = $('#tblData').DataTable({
        "ajax": {
            "url": "/Admin/Order/" + url
        },
        "columns": [
            { "data": "id", "width": "15%" },
            { "data": "name", "width": "15%" },
            { "data": "phoneNumber", "width": "15%" },
            { "data": "applicationUser.email", "width": "15%" },
            { "data": "orderStatus", "width": "15%" },
            { "data": "orderTotal", "width": "15%" },
            {
                "data": "id",
                "render": function (data) {
                    return `
                            <div class="row text-center">
                                <a href="/Admin/Order/Details/${data}" class="btn btn-success text-white" style="cursor:pointer">
                                    <i class="fas fa-edit"></i>
                                </a>
                            </div>
                            `;
                }, "width": "10%"
            }
        ]
    });
}

Results

enter image description here

enter image description here

Thanks!

like image 794
Jesus Hedo Avatar asked Apr 27 '20 12:04

Jesus Hedo


People also ask

How do I use routing in .NET Core?

Routing uses a pair of middleware, registered by UseRouting and UseEndpoints: UseRouting adds route matching to the middleware pipeline. This middleware looks at the set of endpoints defined in the app, and selects the best match based on the request. UseEndpoints adds endpoint execution to the middleware pipeline.

How do I enable routing in .NET Core?

Inside the ConfigureRoute method, you can configure your routes; you can see that this method has to take a parameter of type IRouteBuilder. The goal of routing is to describe the rules that ASP.NET Core MVC will use to process an HTTP request and find a controller that can respond to that request.

What are required parameters for routing?

You need to provide at least two parameters in MapRoute, route name, and URL pattern.


Video Answer


1 Answers

Check the Microsoft Routing Documentation

A route template looks similar to a URI path, but it can have placeholder values, indicated with curly braces

So the [Route("/[area]/[controller]/[action]?id={id}")] is not a valid route, thus the error 500

If you want to pass something as a Query parameter, use the FromQuery attribute.

You can also have multiple Get Methods in the same controller with different routes

    [Route("Index")]
    [HttpGet]
    public IActionResult Index()
    {
        return View();
    }

If you are sending a Query Parameter to the index, add it to the parameters too

    [Route("Index")]
    [HttpGet]
    public IActionResult Index(string status)
    {
        return View();
    }

By the way, you also have a typo:

loadDataTable("GetOrderList/status=pending");
like image 87
Athanasios Kataras Avatar answered Oct 23 '22 05:10

Athanasios Kataras