Bir diziyi ASP.NET MVC denetleyici eylem parametresi olarak nasıl kabul ederim?


86

DesignsAşağıdaki imzaya sahip bir eylemi olan bir ASP.net MVC denetleyicim var:

public ActionResult Multiple(int[] ids)

Ancak, url'yi kullanarak bu eyleme gitmeye çalıştığımda:

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

idsParametre her zaman boş. MVC'nin ?ids=URL sorgu parametresini eylem için bir diziye dönüştürmesini sağlamanın herhangi bir yolu var mı ? Bir eylem filtresi kullanmaktan bahsettiğimi gördüm, ancak söyleyebildiğim kadarıyla bu yalnızca dizinin URL'nin kendisi yerine istek verilerinde geçirildiği POST'lar için çalışacak.

Yanıtlar:


153

Varsayılan model bağlayıcı şu url'yi bekler:

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

başarıyla bağlanmak için:

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

Bunun virgülle ayrılmış değerlerle çalışmasını istiyorsanız, özel bir model bağlayıcı yazabilirsiniz:

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();
    }
}

ve sonra bu model bağlayıcısını belirli bir eylem argümanına uygulayabilirsiniz:

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

veya tüm tamsayı dizisi parametrelerine küresel uygulamak Application_Startin Global.asax:

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

ve şimdi denetleyici eyleminiz şöyle görünebilir:

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

2
Eksiktim [FromUri]. public ActionResult Multiple([FromUri]int[] ids) {} (GET)
C0d1ngJammer

1
@Darin, özel bağlamayı global olarak uygulamanın bir yolu var, ancak belirli eylemler için göz ardı etmenin bir yolu var mı? Bunu yapmanın bir yolunu bulamadım: stackoverflow.com/questions/45379040/…
akd

15

Darin Dimitrov'un cevabını genişletmek için , kurtulabileceğiniz bir şey string, URL parametrenizde basit bir kabul etmek ve bunu kendiniz bir diziye dönüştürmektir:

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

Bunu yaparken bir ayrıştırma hatası alırsanız (birisi size hatalı biçimlendirilmiş bir dizi geçirdiği için), istisna işleyicinizin 400 Bad Requestvarsayılan yerine bir hata döndürmesine neden olabilirsiniz, 404 Not Foundbir uç nokta bulunmadığında MVC'nin döndürdüğü daha dostça olmayan bir hata.


9

Bu URL biçimini de kullanabilirsiniz ve ASP.NET MVC sizin için her şeyi yapacaktır. Ancak, URL kodlamasını uygulamayı unutmayın.

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

6

Groky'nin URL dizesinin nereden geldiğini bilmiyorum, ancak bazı javascript'in denetleyicimi / eylemimi çağırmasıyla aynı sorunu yaşadım. nullÇoklu seçim listesinden (paylaşacağım çözüme özgü) bir URL , 1 veya daha fazla "Kimlik" oluşturur.

Darin'in özel model bağlayıcısını kopyaladım / yapıştırdım ve eylemimi / parametremi dekore ettim, ancak işe yaramadı. Hala nulldeğerlendim int[] ids. Aslında birçok kimliğim olduğu "güvenli" durumda bile.

Javascript'i ASP.NET MVC dostu bir parametre dizisi üretmek için değiştirdim.

?ids=1&ids=2

Yine de bazı aptalca şeyler yapmak zorunda kaldım

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

Yani tam blok

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

Dağınık, ama javascript'te ilk defa böyle hacklemek zorunda kaldım.


2
Son cümlede "ilk sefer" den önce eksik bir "değil" olup olmadığını merak ediyorum. Aksi takdirde, şanslısın!
DCShannon

1
@DCShannon: haha, amacınızı anlıyorum! Ama bu benim ilk seferimdi. Bu tür bir şeyin normal olup olmadığından veya denize mi düşeceğimden emin değilim.
Anthony Mastrean

1

.Net Core Cevap

Son zamanlarda buraya gelenler için, bunu .Net Core'da aşağıdakilerle yapabilirsiniz:

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

ve:

public ActionResult Multiple([FromQuery] int[] ids)
{
    ...
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.