Làm cách nào để chấp nhận một mảng làm tham số hành động của bộ điều khiển ASP.NET MVC?


84

Tôi có bộ điều khiển ASP.net MVC được gọi Designscó tác vụ với chữ ký sau:

public ActionResult Multiple(int[] ids)

Tuy nhiên, khi tôi cố gắng điều hướng đến hành động này bằng cách sử dụng url:

http://localhost:54119/Designs/Multiple?ids=24041,24117

Các idstham số luôn luôn là null. Có cách nào để lấy MVC chuyển đổi ?ids=tham số truy vấn URL thành một mảng cho hành động không? Tôi đã thấy nói về việc sử dụng bộ lọc hành động nhưng theo như tôi có thể nói rằng điều đó sẽ chỉ hoạt động đối với các POST trong đó mảng được chuyển trong dữ liệu yêu cầu chứ không phải trong chính URL.

Câu trả lời:


150

Trình kết nối mô hình mặc định mong đợi url này:

http://localhost:54119/Designs/Multiple?ids=24041&ids=24117

để liên kết thành công với:

public ActionResult Multiple(int[] ids)
{
    ...
}

Và nếu bạn muốn điều này hoạt động với các giá trị được phân tách bằng dấu phẩy, bạn có thể viết trình kết dính mô hình tùy chỉnh:

public class IntArrayModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        if (value == null || string.IsNullOrEmpty(value.AttemptedValue))
        {
            return null;
        }

        return value
            .AttemptedValue
            .Split(',')
            .Select(int.Parse)
            .ToArray();
    }
}

và sau đó bạn có thể áp dụng chất kết dính mô hình này cho một đối số hành động cụ thể:

public ActionResult Multiple([ModelBinder(typeof(IntArrayModelBinder))] int[] ids)
{
    ...
}

hoặc áp dụng nó trên toàn cầu cho tất cả các tham số mảng số nguyên Application_Starttrong Global.asax:

ModelBinders.Binders.Add(typeof(int[]), new IntArrayModelBinder());

và bây giờ hành động của bộ điều khiển của bạn có thể trông giống như sau:

public ActionResult Multiple(int[] ids)
{
    ...
}

2
Tôi đã mất tích [FromUri]. public ActionResult Multiple([FromUri]int[] ids) {} (NHẬN)
C0d1ngJammer

1
@Darin có cách nào để áp dụng ràng buộc tùy chỉnh trên toàn cầu nhưng chỉ bỏ qua cho hành động cụ thể không? Tôi không thể tìm thấy một cách để làm điều đó: stackoverflow.com/questions/45379040/...
AKD

15

Để mở rộng câu trả lời của Darin Dimitrov , điều bạn có thể bỏ qua là chấp nhận một stringtham số URL đơn giản và tự chuyển đổi nó thành một mảng:

public ActionResult Multiple(string ids){
  int[] idsArray = ids.Split(',').Select(int.Parse).ToArray();
  /* ...process results... */
}

Nếu bạn gặp lỗi phân tích cú pháp trong khi thực hiện việc này (do ai đó đã chuyển cho bạn một mảng không đúng định dạng), bạn có thể khiến trình xử lý ngoại lệ trả về 400 Bad Requestlỗi thay vì lỗi mặc định, không thân thiện hơn 404 Not Foundmà MVC trả về khi không tìm thấy điểm cuối.


9

Bạn cũng có thể sử dụng định dạng URL này và ASP.NET MVC sẽ làm mọi thứ cho bạn. Tuy nhiên, hãy nhớ áp dụng mã hóa URL.

?param1[0]=3344&param1[1]=2222

6

Tôi không biết chuỗi URL của Groky đến từ đâu, nhưng tôi đã gặp vấn đề tương tự với một số javascript gọi bộ điều khiển / hành động của tôi. Nó sẽ tạo ra một URLnull , 1 hoặc nhiều "ID" từ một danh sách nhiều lựa chọn (đó là giải pháp duy nhất mà tôi sẽ chia sẻ).

Tôi sao chép / dán chất kết dính mô hình tùy chỉnh của Darin và trang trí hành động / thông số của mình, nhưng nó không hoạt động. Tôi vẫn có nullgiá trịint[] ids . Ngay cả trong trường hợp "an toàn", nơi tôi thực sự có nhiều ID.

Tôi đã kết thúc việc thay đổi javascript để tạo ra một mảng tham số thân thiện với ASP.NET MVC như

?ids=1&ids=2

Tuy nhiên, tôi đã phải làm một số việc ngớ ngẩn

ids || []                 #=> if null, get an empty array
[ids || []]               #=> if a single item, wrap it in an array
[].concat.apply([], ...)  #=> in case I wrapped an array, flatten it

Vì vậy, khối đầy đủ là

ids = [].concat.apply([], [ids || []])
id_parameter = 'ids=' + ids.join('&ids=')

Thật là lộn xộn, nhưng đây là lần đầu tiên tôi phải hack như thế này trong javascript.


1
Chỉ tò mò nếu có thiếu "not" trước "lần đầu tiên" trong câu cuối cùng đó. Nếu không, bạn thật may mắn!
DCShannon

1
@DCShannon: haha, tôi thấy quan điểm của bạn! Nhưng, đây là lần đầu tiên của tôi. Tôi không chắc liệu điều này là bình thường hay tôi đang đi quá đà.
Anthony Mastrean

0

Câu trả lời .Net Core

Đối với những người đến đây trong thời gian gần đây, bạn có thể thực hiện việc này trong .Net Core với:

http://localhost:54119/Designs/Multiple?ids=24041&ids=24117

và:

public ActionResult Multiple([FromQuery] int[] ids)
{
    ...
}
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.