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:
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; } }
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.
3 Réponses :
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; } }
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!
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:
=> 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>
Merci Vijay. Assez similaire à la première réponse, je pense que je sais comment y remédier maintenant!
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:
&
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
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.
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.
Cela pourrait aider - stackoverflow.com/questions/38217534/...