2013-07-22 8 views
9

Sto seguendo il article on Attribute Routing in Web API 2 per provare a inviare una matrice via URI:Come inviare un array tramite un URI utilizzando Attribute Routing in Web API?

[HttpPost("api/set/copy/{ids}")] 
public HttpResponseMessage CopySet([FromUri]int[] ids) 

Questo stava lavorando quando si utilizza convenzione a base di routing:

http://localhost:24144/api/set/copy/?ids=1&ids=2&ids=3 

Ma con attributo Routing è non funziona più - Ottengo 404 non trovato.

Se provo questo:

http://localhost:24144/api/set/copy/1 

allora funziona - ottengo un array con un elemento.

Come si usa l'attributo di routing in questo modo?

risposta

13

Il comportamento si stanno notando è più legata alla azione selezione & vincolante piuttosto che Attribute Routing modello.

Se vi aspettate 'id' venire dalla stringa di query, quindi modificare il modello percorso come qui di seguito (perché il modo è stato definito che fa 'id' obbligatoria nel percorso uri):

[HttpPost("api/set/copy")] 

Guardando la tua seconda domanda, stai cercando di accettare un elenco di ID all'interno dello stesso uri, come api/set/copy/[1,2,3]? se sì, non credo che web api abbia un supporto integrato per questo tipo di rilegatura del modello.

È possibile implementare un'associazione di parametri personalizzata come di seguito per ottenerlo (suppongo che ci siano altri modi migliori per ottenere questo come tramite modelbinders e provider di valori, ma non ne sono molto consapevole ... quindi potresti probabilmente bisogno di esplorare quelle opzioni troppo):

[HttpPost("api/set/copy/{ids}")] 
public HttpResponseMessage CopySet([CustomParamBinding]int[] ids) 

Esempio:

[AttributeUsage(AttributeTargets.Parameter, Inherited = false, AllowMultiple = false)] 
public class CustomParamBindingAttribute : ParameterBindingAttribute 
{ 
    public override HttpParameterBinding GetBinding(HttpParameterDescriptor paramDesc) 
    { 
     return new CustomParamBinding(paramDesc); 
    } 
} 

public class CustomParamBinding : HttpParameterBinding 
{ 
    public CustomParamBinding(HttpParameterDescriptor paramDesc) : base(paramDesc) { } 

    public override bool WillReadBody 
    { 
     get 
     { 
      return false; 
     } 
    } 

    public override Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, 
                CancellationToken cancellationToken) 
    { 
     //TODO: VALIDATION & ERROR CHECKS 
     string idsAsString = actionContext.Request.GetRouteData().Values["ids"].ToString(); 

     idsAsString = idsAsString.Trim('[', ']'); 

     IEnumerable<string> ids = idsAsString.Split(','); 
     ids = ids.Where(str => !string.IsNullOrEmpty(str)); 

     IEnumerable<int> idList = ids.Select(strId => 
      { 
       if (string.IsNullOrEmpty(strId)) return -1; 

       return Convert.ToInt32(strId); 

      }).ToArray(); 

     SetValue(actionContext, idList); 

     TaskCompletionSource<object> tcs = new TaskCompletionSource<object>(); 
     tcs.SetResult(null); 
     return tcs.Task; 
    } 
} 
+0

Grazie Kiran. Sono solo confuso perché api/set/copia/ID = 1 & id = 2 & ID = 3 stava lavorando prima, e una tonnellata di miei metodi utilizzano questo schema:?/ – SB2055

+1

Dovrebbe funzionare ormai troppo fino a quando non si ha il ' gli id ​​'definiti nel modello di percorso come: '[HttpPost (" api/set/copy ")]'. Ricordare che il modello di percorso può essere utilizzato solo per definire i percorsi uri e non per eseguire query sui dati di stringa. –

+0

Perfetto. Grazie – SB2055