3
votes

Comment passer plusieurs paramètres à Get Method et les acheminer dans l'API Web .NET Core?

Je crée une API Web (reposante) dans .NET Core et je suis tombé sur des problèmes.

Je n'arrive pas à trouver comment transmettre plusieurs identifiants d'abonnement ... Je dois pouvoir afficher plusieurs périodes (factures) de plusieurs abonnements.

Mon itinéraire pour le moment est [Route ("tenants / {tenantId: long} / subscriptions / {subscriptionId: long} / factures / {factureId: long} / categories")]

De cette façon, il me semble impossible de passer plus identifiants d'abonnement. Certains termes que j'ai trouvés mais que je ne comprends pas entièrement sont:

  • Liaison de modèle
  • [FromQuery Often convenient

Mes classes:

    [HttpGet]
    public IEnumerable<SubscriptionViewModel> Find(long tenantId)
    {
        var subscriptionList = _subscriptionManager.Find(tenantId);
        ...
        return subscriptionViewModels;
    }

    [HttpGet]
    public IEnumerable<InvoiceViewModel> Find(long subscriptionId)
    {
        var invoiceList = _invoiceManager.Find(subscriptionId);
        ...
        return invoiceViewModels;
    }

Mes contrôleurs avec routes [Route ("tenants / {tenantId: long} / subscriptions")] code> et [Route("tenants/{tenantId:long}/subscriptions/{subscriptionId:long}/invoices")

    public class Subscription
    {
    public string Name { get; set; }
    public long TenantId { get; set; }
    public string Guid { get; set; }
    }

    public class Invoice
    {
    public long SubscriptionId { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
    public long PortalId { get; set; }
    }
  • Veuillez noter que j'utilise un Mapper pour mes données (c'est pourquoi j'utilise ViewModels).
  • Le code actuellement rédigé concerne un abonnement spécifique.

Je recherche un itinéraire comme /api/invoices?subscriptionId=x,y,z

Je comprends (?) J'ai besoin du [FromQuery ] pour cela, mais je n'arrive pas à savoir comment, surtout si mon paramètre (subscriptionId) reste le même.


1 commentaires

3 Réponses :


1
votes

Vous pouvez créer un modèle de vue de demande spécifique qui accepte une collection d'ID de facture:

tenants/{tenantId}/subscriptions/{subscriptionId}/invoices?invoiceIDs=1&invoiceIDs=2&invoiceIDs=3

et l'utiliser pour votre méthode d'action:

invoiceIDs=1&invoiceIDs=2&invoiceIDs=3

Dans le cas où vous souhaitez utiliser des paramètres de requête, marquez votre paramètre d'action avec l'attribut [FromQuery] :

[Route("tenants/{tenantId:long}/subscriptions/{subscriptionId:long}/invoices")]
[HttpGet]
public IEnumerable<InvoiceViewModel> Get([FromQuery]IEnumerable<long> invoiceIDs)
{

}

et lors de la création de la requête, passez chaque valeur avec la même clé dans la chaîne de requête:

[Route("tenants/{tenantId:long}/subscriptions/{subscriptionId:long}/invoices")]
[HttpGet]
public IEnumerable<InvoiceViewModel> Get(InvoiceRequestModel requestModel)
{

}

Enfin, cela ressemblera à ceci:

public class InvoiceRequestModel
{
    IEnumerable<long> InvoiceIDS { get; set; }
}


3 commentaires

Merci, je vais certainement essayer ceci si les autres méthodes ne fonctionnent pas mais je préfère ne pas créer de ViewModel spécifique. Merci!


@NielsSchepers La création d'un RequestModel est une bonne pratique. Avez-vous des raisons de ne pas le faire?


Mon projet est complètement mappé et j'essaye de garder les vues de modèle mappées. Ce qui signifie que si j'ajoute un autre ModelView, il n'y a nulle part où le mapper (ce qui est évidemment le but), mais à moins que j'aie vraiment à le faire, j'essaie d'éviter de créer des modèles supplémentaires. Je garderai définitivement cette méthode à l'esprit, c'était quelque chose auquel je n'avais pas pensé auparavant. EDit: je suis presque sûr que c'est la solution la plus correcte, ne vous méprenez pas!



1
votes

Il peut y avoir plusieurs façons d'accomplir cette tâche (je peux penser à deux-trois pour le moment).

1) au lieu d'un long subscriptionid, prenez une chaîne comme entrée et validez-la avant de continuer.

[HttpGet]
public IEnumerable<InvoiceViewModel> Find(string subscriptionIds)
{
    var list = validateInput(subscriptionIds);
    var invoiceList = _invoiceManager.FindList(list);
    ...
    return invoiceViewModels;
}

public IList<long> validateInput(string subscriptionIds)
{
    var list = subscriptionIds.Split(",");
    ... // Code to convert each element in long and throw if it is not long
    return longlist;
}

2) Créez des classeurs de modèles personnalisés.

Les étapes sont mentionnées ici:

https://docs.microsoft.com / fr-fr / aspnet / web-api / overview / formats-and-model-binding / parameter-binding-in-aspnet-web-api

=> L'attribut [FromUri] peut être utilisé pour lier les types complexes à partir des paramètres de chaîne de requête, mais je ne sais pas comment j'utiliserais cela.

Si vous me le demandez, je choisirais l'approche-1 (pour ne pas augmenter la complexité). p>


1 commentaires

Merci Vijay. Assez similaire à la première réponse, je pense que je sais comment y remédier maintenant!



2
votes

pour l'exigence que vous avez mentionnée comme:

Je recherche une route comme / api / factures? subscriptionId = x, y, z

Vous pouvez faire deux choses:

  1. passez les subscriptionIds les uns après les autres séparés par & dans la chaîne de requête de l'URL et modifiez le paramètre d'entrée de la méthode d'action pour accepter le tableau de subscriptionIds exemple d'itinéraire:
public IEnumerable<InvoiceViewModel> Find([FromQuery]string subscriptionIds)
{
    var ids = subscriptionIds.Split(',').Select(int.Parse).ToArray();
    // do the logic on multiple subscriptionIds
}

exemple de paramètre de méthode d'action acceptant un tableau de subscriptionIds:

/api/invoices/find?subscriptionIds=x,y,z
  1. transmettez la chaîne séparée par des virgules en tant que chaîne de requête dans l'URL et écrivez un élément de logique dans la méthode d'action pour diviser la chaîne en fonction de la virgule pour obtenir un tableau de subscriptionIds exemple d'itinéraire:
public IEnumerable<InvoiceViewModel> Find([FromQuery]long[] subscriptionId)

exemple de méthode d'action:

/api/invoices/find?subscriptionId=x&subscriptionId=y&subscriptionId=z

En dehors de cela, vous pouvez créer des classeurs de modèles personnalisés ainsi que suggéré dans d'autres réponses.

J'espère que cela vous aidera.


2 commentaires

Si cela vous aide, veuillez cocher la réponse. Merci


La solution No2 est une conception très médiocre pour un point de terminaison d'API, à la fois techniquement et sémantiquement.