ASP.NET MVC - chuyển các tham số đến bộ điều khiển


105

Tôi có bộ điều khiển với phương thức hành động như sau:

public class InventoryController : Controller
{
    public ActionResult ViewStockNext(int firstItem)
    {
        // Do some stuff
    }
}

Và khi tôi chạy nó, tôi gặp lỗi cho biết:

Từ điển tham số không chứa giá trị hợp lệ kiểu 'System.Int32' cho tham số 'firstItem'. Để làm cho một tham số là tùy chọn, kiểu của nó phải là kiểu tham chiếu hoặc kiểu Nullable.

Tôi đã có nó hoạt động tại một thời điểm và tôi quyết định thử chức năng không có tham số. Phát hiện ra rằng bộ điều khiển không tồn tại, tôi đã đặt lại tham số, bây giờ nó từ chối nhận ra tham số khi tôi gọi phương thức.

Tôi đang sử dụng cú pháp url này để gọi hành động:

http://localhost:2316/Inventory/ViewStockNext/11

Bất kỳ ý tưởng nào tại sao tôi lại gặp lỗi này và tôi cần làm gì để khắc phục nó?

Tôi đã thử thêm một phương thức khác nhận một số nguyên vào lớp, nó cũng không thành công với lý do tương tự. Tôi đã thử thêm một chuỗi có chuỗi và chuỗi được đặt thành null. Tôi đã thử thêm một cái mà không có tham số và điều đó hoạt động tốt, nhưng tất nhiên nó sẽ không phù hợp với nhu cầu của tôi.

Câu trả lời:


106

Định tuyến của bạn cần phải được thiết lập dọc theo {controller}/{action}/{firstItem}. Nếu bạn để định tuyến làm mặc định {controller}/{action}/{id}trong global.asax.cstệp của mình , thì bạn sẽ cần phải đăng nhập id.

routes.MapRoute(
    "Inventory",
    "Inventory/{action}/{firstItem}",
    new { controller = "Inventory", action = "ListAll", firstItem = "" }
);

... hoặc một cái gì đó gần đó.


44
Hoặc chỉ cần đổi tên "firstItem" thành "id"
Kyle Trauberman

8
Thêm vào đó nó thế giới là khôn ngoan để thêm một đối tượng hạn chế đến MapRoute, như vậy: new { firstItem = @"\d" }. Bằng cách này, nó sẽ chỉ chấp nhận nếu tham số là bất kỳ loại số nào. Bạn có thể sửa đổi regex theo ý muốn và thậm chí giới hạn số lượng số thập phân, như thế này: new { firstItem = @"\d{4}" }- bây giờ nó chỉ có thể dài 4 số. Chỉnh sửa: ví dụ về MapRoute
KristianB

86

bạn có thể thay đổi firstItem thành id và nó sẽ hoạt động

bạn có thể thay đổi định tuyến trên global.asax (tôi không đề nghị điều đó)

và, không thể tin rằng không có ai đề cập đến điều này, bạn có thể gọi:

http://localhost:2316/Inventory/ViewStockNext?firstItem=11

Trong một @ Url. Hành động sẽ là:

@Url.Action("ViewStockNext", "Inventory", new {firstItem=11});

tùy thuộc vào loại công việc bạn đang làm, cuối cùng sẽ phù hợp hơn. Ngoài ra, bạn nên xem xét không thực hiện hành động ViewStockNext và thay vào đó là một hành động ViewStock với chỉ mục. (2 xu của tôi)


15

Để diễn đạt lại câu trả lời của Jarret Meyer , bạn cần thay đổi tên tham số thành 'id' hoặc thêm một tuyến đường như sau:

routes.MapRoute(
        "ViewStockNext", // Route name
        "Inventory/ViewStockNext/{firstItem}",  // URL with parameters
        new { controller = "Inventory", action = "ViewStockNext" }  // Parameter defaults
    );

Lý do là tuyến mặc định chỉ tìm kiếm các hành động không có tham số hoặc tham số được gọi là 'id'.

Chỉnh sửa: Heh, đừng bận tâm Jarret đã thêm một ví dụ về tuyến đường sau khi đăng.


8

hoặc làm điều đó với Thuộc tính tuyến:

public class InventoryController : Controller
{
    [Route("whatever/{firstItem}")]
    public ActionResult ViewStockNext(int firstItem)
    {
        int yourNewVariable = firstItem;
        // ...
    }
}

Thuộc tính này có thể không hoạt động với các phiên bản MVC cũ hơn.
Tiến sĩ Suat Atan

Ngoài ra, để điều này hoạt động, bạn cần đảm bảo rằng bạn đã gọi routes.MapMvcAttributeRoutes();trong RegisterRoutes(RouteCollection)phương thức của ứng dụng (thường được đưa vào App_Start \ RouteConfig.cs). Nó có thể không ở đó theo mặc định.
Daniel Scott

7

Headspring đã tạo một thư viện đẹp cho phép bạn thêm bí danh vào các tham số của mình trong các thuộc tính của hành động. Nó trông như thế này:

[ParameterAlias("firstItem", "id", Order = 3)]
public ActionResult ViewStockNext(int firstItem)
{
    // Do some stuff
}

Với điều này, bạn không phải thay đổi định tuyến của mình chỉ để xử lý một tên tham số khác. Thư viện cũng hỗ trợ áp dụng nó nhiều lần để bạn có thể ánh xạ một số cách viết tham số (tiện lợi khi cấu trúc lại mà không phá vỡ giao diện công cộng của bạn).

Bạn có thể lấy nó từ Nuget và đọc bài viết của Jeffrey Palermo về nó tại đây


7

public ActionResult ViewNextItem(int? id)làm cho idsố nguyên trở thành một kiểu nullable, không cần chuyển đổi chuỗi <-> int.


3

Sử dụng tính năng ASP.NET Core Tag Helper:

<a asp-controller="Home" asp-action="SetLanguage" asp-route-yourparam1="@item.Value">@item.Text</a>

Trớ trêu thay, câu trả lời ngắn nhất lại là câu trả lời tốt nhất (câu trả lời này).

1

Có một cách khác để thực hiện điều đó (được mô tả chi tiết hơn trong ví dụ về Máy nhắn tin của Stephen Walther

Về cơ bản, bạn tạo một liên kết trong dạng xem:

Html.ActionLink("Next page", "Index", routeData)

Trong routeData, bạn có thể chỉ định các cặp tên / giá trị (ví dụ: routeData ["page"] = 5), và trong hàm Index của bộ điều khiển các tham số tương ứng nhận giá trị. Đó là,

public ViewResult Index(int? page)

sẽ có trang được chuyển là 5. Tôi phải thừa nhận, khá bất thường khi chuỗi ("trang") tự động trở thành một biến - nhưng đó là cách MVC hoạt động trong các ngôn ngữ khác ...


0

Lý do cho cách xử lý đặc biệt của "id" là nó được thêm vào ánh xạ tuyến đường mặc định. Để thay đổi điều này, hãy truy cập Global.asax.cs và bạn sẽ thấy dòng sau:

routes.MapRoute ("Default", "{controller}/{action}/{id}", 
                 new { controller = "Home", action = "Index", id = "" });

Thay đổi nó thành:

routes.MapRoute ("Default", "{controller}/{action}", 
                 new { controller = "Home", action = "Index" });

0

Hoặc, bạn có thể thử thay đổi kiểu tham số thành chuỗi, sau đó chuyển đổi chuỗi thành số nguyên trong phương thức. Tôi mới sử dụng MVC, nhưng tôi tin rằng bạn cần các đối tượng nullable trong danh sách tham số của mình, làm thế nào khác bộ điều khiển sẽ chỉ ra rằng không có tham số như vậy được cung cấp? Vì thế...

public ActionResult ViewNextItem(string id)...
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.