Chaîne de requête ne fonctionne pas lors de l’utilisation du routage d’atsortingbut

J’utilise System.Web.Http.RouteAtsortingbute et System.Web.Http.RoutePrefixAtsortingbute pour activer les URL plus propres pour mon application Web API 2. Pour la plupart de mes demandes, je peux utiliser le routage (par exemple Controller/param1/param2 ) ou utiliser des chaînes de requête (par exemple, Controller?param1=bob&param2=mary ).

Malheureusement, avec l’un de mes contrôleurs (et un seul), cela échoue. Voici mon contrôleur:

 [RoutePrefix("1/Names")] public class NamesController : ApiController { [HttpGet] [Route("{name}/{sport}/{drink}")] public List Get(ssortingng name, ssortingng sport, ssortingng drink) { // Code removed... } [HttpGet] [Route("{name}/{drink}")] public List Get(ssortingng name, ssortingng drink) { // Code removed... } } 

Lorsque je fais une demande de routage, les deux fonctionnent correctement. Cependant, si j’utilise une chaîne de requête, cela échoue, me disant que ce chemin n’existe pas.

J’ai essayé d’append ce qui suit à ma fonction WebApiConfig.csRegister(HttpConfiguration config) (avant et après la route par défaut), mais cela n’a rien fait:

 config.Routes.MapHttpRoute( name: "NameRoute", routeTemplate: "{verId}/Names/{name}/{sport}/{drink}", defaults: new { name = RouteParameter.Optional, sport = RouteParameter.Optional, drink = RouteParameter.Optional }, constraints: new { verId = @"\d+" }); 

Donc, pour plus de clarté, j’aimerais pouvoir faire les deux:

 localhost:12345/1/Names/Ted/rugby/coke localhost:12345/1/Names/Ted/coke 

et,

 localhost:12345/1/Names?name=Ted&sport=rugby&drink=coke localhost:12345/1/Names?name=Ted&drink=coke 

mais malheureusement les versions de chaîne de requête ne fonctionnent pas! 🙁

Actualisé

J’ai complètement supprimé la deuxième action et essaye maintenant d’utiliser une action singulière avec des parameters facultatifs. J’ai changé mon atsortingbut de [Route("{name}/{drink}/{sport?}")] Car Tony a suggéré de rendre le sport nullable, mais cela empêche désormais localhost:12345/1/Names/Ted/coke d’être un itinéraire valide pour une raison quelconque. Les chaînes de requête se comportent de la même manière qu’auparavant.

Mise à jour 2 J’ai maintenant une action singulière dans mon contrôleur:

 [RoutePrefix("1/Names")] public class NamesController : ApiController { [HttpGet] [Route("{name}/{drink}/{sport?}")] public List Get(ssortingng name, ssortingng drink, ssortingng sport = "") { // Code removed... } } 

Cependant, l’utilisation de chaînes de requête ne permet pas de trouver un chemin approprié, contrairement à la méthode de routage.

J’étais confronté au même problème de «Comment inclure des parameters de recherche en tant que chaîne de requête?» Alors que j’essayais de créer une API Web pour mon projet actuel. Après googling, ce qui suit fonctionne bien pour moi:

Action du contrôleur Api:

 [HttpGet, Route("search/{categoryid=categoryid}/{ordercode=ordercode}")] public Task GetProducts(ssortingng categoryId, ssortingng orderCode) { } 

L’URL que j’ai essayé par l’intermédiaire du postier:

 http://localhost/PD/search?categoryid=all-products&ordercode=star-1932 http://localhost/PD is my hosted api 

Après beaucoup de sortingpotage minutieux et de recherche sur Google, j’ai trouvé une solution. Je ne sais pas si c’est l’idéal / la meilleure pratique / le vieux faux, mais cela résout mon problème.

Tout ce que j’ai fait a été d’append [Route("")] en plus des atsortingbuts de route que j’utilisais déjà. Cela permet essentiellement au routage Web API 2 d’autoriser les chaînes de requête, car il s’agit désormais d’un itinéraire valide.

Un exemple serait maintenant:

 [HttpGet] [Route("")] [Route("{name}/{drink}/{sport?}")] public List Get(ssortingng name, ssortingng drink, ssortingng sport = "") { // Code removed... } 

Cela rend les deux localhost:12345/1/Names/Ted/coke et localhost:12345/1/Names?name=Ted&drink=coke valide.

Avec le routage d’atsortingbut, vous devez spécifier des valeurs par défaut afin qu’elles soient facultatives.

 [Route("{name}/{sport=Football}/{drink=Coke}")] 

L’atsortingbution d’une valeur lui permet d’être optionnelle, vous n’avez donc pas à l’inclure et elle passera la valeur à spécifier.

Je n’ai pas testé la chaîne de requête pour cela, mais cela devrait fonctionner de la même manière.

Je viens de relire la question et je vois que vous avez 2 verbes Get avec le même chemin, je crois que cela provoquerait un conflit car le routage ne saurait pas lequel utiliser, peut-être que l’aide des parameters optionnels aidera. Vous pouvez également spécifier que l’on peut être nul et vérifier la méthode pour procéder.

 [Route("{name}/{sport?}/{drink?}")] 

Ensuite, vérifiez les variables de la méthode pour voir si elles sont nulles et manipulez-les selon vos besoins.

J’espère que cela aide, certains? lol

Si ce n’est peut-être pas le cas, le site aura plus de détails sur le routage des atsortingbuts.

http://www.asp.net/web-api/overview/web-api-routing-and-actions/atsortingbute-routing-in-web-api-2

Clip à partir de ce site:

Paramètres facultatifs et valeurs par défaut Vous pouvez spécifier qu’un paramètre est facultatif en ajoutant un point d’interrogation au paramètre, à savoir:

 [Route("counsortinges/{name?}")] public Country GetCountry(ssortingng name = "USA") { } 

Actuellement, une valeur par défaut doit être spécifiée sur le paramètre facultatif pour que la sélection d’action réussisse, mais nous pouvons étudier la possibilité de lever cette ressortingction. (S’il vous plaît laissez-nous savoir si cela est important.)

Les valeurs par défaut peuvent être spécifiées de la même manière:

 [Route("counsortinges/{name=USA}")] public Country GetCountry(ssortingng name) { } 

Le paramètre optionnel ‘?’ et les valeurs par défaut doivent apparaître après les contraintes en ligne dans la définition du paramètre.

Juste une note latérale de ma part aussi. Pour que paramS de querySsortingng fonctionne, vous devez fournir une valeur par défaut pour vos parameters de méthode afin de la rendre facultative . Tout comme vous le feriez également lorsque vous invoquez une méthode C #.

 [RoutePrefix("api/v1/profile")] public class ProfileController : ApiController { ... [HttpGet] [Route("{profileUid}")] public IHttpActionResult GetProfile(ssortingng profileUid, long? someOtherId) { // ... } ... } 

Cela me permet d’appeler le point final comme ceci:

 /api/v1/profile/someUid /api/v1/profile/someUid?someOtherId=123 

L’utilisation de Route("search/{categoryid=categoryid}/{ordercode=ordercode}") vous permettra d’utiliser les parameters Queryssortingngs et les parameters de routage en ligne, auxquels Mosharaf Hossain a répondu . Ecrire cette réponse car cela devrait être la meilleure réponse. Utiliser Route("") posera des problèmes si vous avez plusieurs Gets / Puts / Posts / Deletes.

Voici un léger écart par rapport à la réponse de @bhargav kishore mummadireddy , mais une déviation importante. Sa réponse impliquera par défaut les valeurs de chaîne de requête à une valeur non vide réelle. Cette réponse leur sera par défaut vide.

Il vous permet d’appeler le contrôleur via le routage du chemin ou en utilisant la chaîne de requête. Essentiellement, il définit la valeur par défaut de la chaîne de requête à vider, ce qui signifie qu’elle sera toujours routée.

Cela était important pour moi, car je veux renvoyer 400 (Mauvaise demande) si une chaîne de requête n’est pas spécifiée, plutôt que de renvoyer ASP.NET dans l’erreur “Impossible de localiser cette méthode sur ce contrôleur”.

 [RoutePrefix("api/AppUsageReporting")] public class AppUsageReportingController : ApiController { [HttpGet] // Specify default routing parameters if the parameters aren't specified [Route("UsageAggregationDaily/{userId=}/{startDate=}/{endDate=}")] public async Task UsageAggregationDaily(ssortingng userId, DateTime? startDate, DateTime? endDate) { if (Ssortingng.IsNullOrEmpty(userId)) { return Request.CreateResponse(HttpStatusCode.BadRequest, $"{nameof(userId)} was not specified."); } if (!startDate.HasValue) { return Request.CreateResponse(HttpStatusCode.BadRequest, $"{nameof(startDate)} was not specified."); } if (!endDate.HasValue) { return Request.CreateResponse(HttpStatusCode.BadRequest, $"{nameof(endDate)} was not specified."); } } } 

Puisque vous avez [Route("{name}/{drink}/{sport?}")] tant que routage d’atsortingbut, ce code ne sera jamais touché.

 config.Routes.MapHttpRoute( name: "NameRoute", routeTemplate: "{verId}/Names/{name}/{sport}/{drink}", defaults: new { name = RouteParameter.Optional, sport = RouteParameter.Optional, drink = RouteParameter.Optional }, constraints: new { verId = @"\d+" }); 

Donc, seul l’atsortingbut route [Route("{name}/{drink}/{sport?}")] Sera honoré ici. Depuis votre demande localhost:12345/1/Names?name=Ted&sport=rugby&drink=coke , n’a pas de nom, de sport ou de boisson dans l’URL, elle ne correspondra pas à cet atsortingbut. Nous ne considérons pas les parameters de chaîne de requête lors de la correspondance des routes.

Pour résoudre ce problème, vous devez rendre les 3 options facultatives dans votre itinéraire d’atsortingbut. Ensuite, il correspondra à la demande.

J’utilise l’atsortingbut FromUri comme solution

 [Route("UsageAggregationDaily")] public async Task UsageAggregationDaily([FromUri] ssortingng userId = null, [FromUri] DateTime? startDate = null, [FromUri] DateTime? endDate = null)