首页 > 解决方案 > 如何在 ASP.NET Core 3.1 中使用参数进行路由

问题描述

在 ASP.NET Core 3.1 中,当我在控制器中指定路由时,必须是那种

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

但是当它像

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

它返回错误 500。

我想在路由中显示来自 JS 的 TableData

 Admin/Order/Index?status={status}

但是,在控制器中,HttpGet 是操作GetOrderList,因此数据被发送到

Admin/Order/GetOrderList?status={status}

我怎样才能正确配置路由?

控制器:

[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
}

索引视图:

@{
    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%"
            }
        ]
    });
}

结果

在此处输入图像描述

在此处输入图像描述

谢谢!

标签: c#asp.net-coreasp.net-core-3.1

解决方案


检查Microsoft 路由文档

路由模板看起来类似于 URI 路径,但它可以有占位符值,用花括号表示

所以这[Route("/[area]/[controller]/[action]?id={id}")]不是一个有效的路线,因此错误 500

如果您想将某些内容作为 Query 参数传递,请使用该FromQuery属性。

您还可以在具有不同路由的同一控制器中拥有多个 Get 方法

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

如果要向索引发送查询参数,请将其也添加到参数中

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

顺便说一句,你还有一个错字:

loadDataTable("GetOrderList/status=pending");

推荐阅读