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
Thanks!
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.
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.
You need to provide at least two parameters in MapRoute, route name, and URL pattern.
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");
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With