c# - mvc - ¿Por qué es que "No se encontró ningún recurso HTTP que coincida con el URI de solicitud" aquí?
web api 2 url parameters (5)
Si se trata de un servicio GET, debe usarlo con un método GET, no con un método POST. Tu problema es un error de tipo. Un ejemplo diferente de desajuste de tipo (para poner la gravedad en perspectiva) es intentar asignar una cadena a una variable entera.
Tengo un código en mi controlador así:
[Route("api/deliveryitems/InsertIntoPPTData/{stringifiedRecord}")]
... y lo estoy llamando a través de Postman como tal:
http://localhost:21609/api/deliveryitems/InsertIntoPPTData?
stringifiedRecord=serNum77;tx2;siteNum2;bla2.xml;ppt_user2;tx_memo2;file_beg2;file_end2
... pero consigue:
{
Message: "No HTTP resource was found that matches the request URI
''http://localhost:21609/api/deliveryitems/InsertIntoPPTData? stringifiedRecord=serNum77;tx2;siteNum2;bla2.xml;ppt_user2;tx_memo2;file_beg2;file_end2''."
MessageDetail: "No type was found that matches the controller named ''deliveryitems''."
}
Otros métodos REST que se crean y llaman de la misma manera se encuentran muy bien, ¿por qué no este? Lo único que no tiene en común con los demás es que es un HttpPost, mientras que los otros son HttpGet. ¿Eso hace mucha diferencia? Estoy seleccionando "Publicar" en el menú desplegable de Cartero cuando trato de llamar a este método REST.
ACTUALIZAR
Sí, aparentemente no tiene nada que ver con que sea una publicación y que pase argumentos en el URI, porque estoy obteniendo lo mismo ahora con un método HttpGet:
{
Message: "No HTTP resource was found that matches the request URI
''http://localhost:21609/api/department/getndeptsfromid?firstId=2&countToFetch=12''."
MessageDetail: "No action was found on the controller ''Department'' that matches the request."
}
Lo llamo cartero, así:
http://localhost:21609/api/department/getndeptsfromid?firstId=2&countToFetch=12
... y de hecho aparece en mi controlador:
[HttpGet]
[Route("api/department/getndeptsfromid/{firstId}/{countToFetch}")]
public List<Department> GetNDepartmentsFromID(int FirstId, int CountToFetch)
{
return CCRService.GetNDepartmentsFromID(FirstId, CountToFetch);
}
ACTUALIZACIÓN 2
Pensé que estaba a punto de resolverlo cuando cambié este código:
String.Format("api/department/getndeptsfromid/{0}/{1}", FirstId, CountToFetch)
...a esto:
String.Format("api/department/getndeptsfromid?firstId={0}&countToFetch={1}", FirstId, CountToFetch)
... pero sigo teniendo el mismo error de mensaje ...
ACTUALIZACIÓN 3
Encuentro que esto tampoco funciona:
http://localhost:21609/api/delivery/invnumbyid?ID=33
... y entonces hay un patrón definido. CUALQUIER LLAMADA REST API que hago que contiene argumentos / params falla de esta misma manera; todos los demás ( http://localhost:21609/api/deliveries/Count, http://localhost:21609/api/deliveryitems/count, http://localhost:21609/api/department/getall
) funcionan bien . IOW, si no hay argumentos en el URI, se descubre el método. Si hay args, no lo es.
Entonces, aparentemente, hay algo mal con la forma en que paso los argumentos / vals en el URI (se agrega " ? = " En el caso de un único argumento y, en el caso de dos argumentos " ? = & = ") Y / o hay algo mal con la forma en que configuro el enrutamiento. Específicamente, este estilo funciona:
[Route("api/Deliveries/Count")]
... mientras que este estilo no:
[Route("api/delivery/invnumbyid/{ID}")]
Generaré esta pregunta CUANTO ANTES: 50 puntos para el desenredador de este nudo Gordiesco, y 100 si se responde hoy (antes de la configuración de la recompensa).
ACTUALIZACIÓN 4
Cambié el enrutamiento para incluir el tipo de datos del arg para que esto:
[Route("api/delivery/invnumbyid/{ID}")]
-se llegó a esto:
[Route("api/delivery/invnumbyid/{ID:int}")]"
Pero todavía falló, gruñendo:
{
Message: "No HTTP resource was found that matches the request URI
''http://localhost:21609/api/delivery/invnumbyid?ID=45''."
MessageDetail: "No action was found on the controller ''Delivery'' that matches the request."
}
Luego, "en una alondra", intenté ingresar esto en Postman:
http://localhost:21609/api/delivery/invnumbyid/45
...¡Y funcionó! (He estado pensando que tenía que ser " http://localhost:21609/api/delivery/invnumbyid?ID=45
")
Pero un intento similar en Postman:
http://localhost:21609/api/department/getndeptsfromid/2/12/
... sigue fallando con "Sin valor para uno o más parámetros requeridos". a pesar de que esto es golpeado:
[HttpGet]
[Route("api/department/getndeptsfromid/{firstId}/{countToFetch}")]
public List<Department> GetNDepartmentsFromID(int FirstId, int CountToFetch)
{
return HHSService.GetNDepartmentsFromID(FirstId, CountToFetch);
}
... y los argumentos a GetNDepartmentsFromID () tienen los vals esperados (2 y 12)
Aún peor / más extraño es el resultado que obtengo con " http://localhost:21609/api/deliveryitems/InsertIntoPPTData/serNum77;tx2;siteNum2;bla2.xml;ppt_user2;tx_memo2;file_beg2;file_end2
" now:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html
xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>IIS 8.0 Detailed Error - 404.0 - Not Found</title>
<style type="text/css">
<!--
body{margin:0;font-size:.7em;font-family:Verdana,Arial,Helvetica,sans-serif;}
code{margin:0;color:#006600;font-size:1.1em;font-weight:bold;}
.config_source code{font-size:.8em;color:#000000;}
pre{margin:0;font-size:1.4em;word-wrap:break-word;}
ul,ol{margin:10px 0 10px 5px;}
ul.first,ol.first{margin-top:5px;}
fieldset{padding:0 15px 10px 15px;word-break:break-all;}
.summary-container fieldset{padding-bottom:5px;margin-top:4px;}
legend.no-expand-all{padding:2px 15px 4px 10px;margin:0 0 0 -12px;}
legend{color:#333333;;margin:4px 0 8px -12px;_margin-top:0px;
font-weight:bold;font-size:1em;}
a:link,a:visited{color:#007EFF;font-weight:bold;}
a:hover{text-decoration:none;}
h1{font-size:2.4em;margin:0;color:#FFF;}
h2{font-size:1.7em;margin:0;color:#CC0000;}
h3{font-size:1.4em;margin:10px 0 0 0;color:#CC0000;}
h4{font-size:1.2em;margin:10px 0 5px 0;
}#header{width:96%;margin:0 0 0 0;padding:6px 2% 6px 2%;font-family:"trebuchet MS",Verdana,sans-serif;
color:#FFF;background-color:#5C87B2;
}#content{margin:0 0 0 2%;position:relative;}
.summary-container,.content-container{background:#FFF;width:96%;margin-top:8px;padding:10px;position:relative;}
.content-container p{margin:0 0 10px 0;
}#details-left{width:35%;float:left;margin-right:2%;
}#details-right{width:63%;float:left;overflow:hidden;
}#server_version{width:96%;_height:1px;min-height:1px;margin:0 0 5px 0;padding:11px 2% 8px 2%;color:#FFFFFF;
background-color:#5A7FA5;border-bottom:1px solid #C1CFDD;border-top:1px solid #4A6C8E;font-weight:normal;
font-size:1em;color:#FFF;text-align:right;
}#server_version p{margin:5px 0;}
table{margin:4px 0 4px 0;width:100%;border:none;}
td,th{vertical-align:top;padding:3px 0;text-align:left;font-weight:normal;border:none;}
th{width:30%;text-align:right;padding-right:2%;font-weight:bold;}
thead th{background-color:#ebebeb;width:25%;
}#details-right th{width:20%;}
table tr.alt td,table tr.alt th{}
.highlight-code{color:#CC0000;font-weight:bold;font-style:italic;}
.clear{clear:both;}
.preferred{padding:0 5px 2px 5px;font-weight:normal;background:#006633;color:#FFF;font-size:.8em;}
-->
</style>
</head>
<body>
<div id="content">
<div class="content-container">
<h3>HTTP Error 404.0 - Not Found</h3>
<h4>The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.</h4>
</div>
<div class="content-container">
<fieldset>
<h4>Most likely causes:</h4>
<ul>
<li>The directory or file specified does not exist on the Web server.</li>
<li>The URL contains a typographical error.</li>
<li>A custom filter or module, such as URLScan, restricts access to the file.</li>
</ul>
</fieldset>
</div>
<div class="content-container">
<fieldset>
<h4>Things you can try:</h4>
<ul>
<li>Create the content on the Web server.</li>
<li>Review the browser URL.</li>
<li>Check the failed request tracing log and see which module is calling SetStatus. For more information, click
<a href="http://go.microsoft.com/fwlink/?LinkID=66439">here</a>.
</li>
</ul>
</fieldset>
</div>
<div class="content-container">
<fieldset>
<h4>Detailed Error Information:</h4>
<div id="details-left">
<table border="0" cellpadding="0" cellspacing="0">
<tr class="alt">
<th>Module</th>
<td> IIS Web Core</td>
</tr>
<tr>
<th>Notification</th>
<td> MapRequestHandler</td>
</tr>
<tr class="alt">
<th>Handler</th>
<td> StaticFile</td>
</tr>
<tr>
<th>Error Code</th>
<td> 0x80070002</td>
</tr>
</table>
</div>
<div id="details-right">
<table border="0" cellpadding="0" cellspacing="0">
<tr class="alt">
<th>Requested URL</th>
<td> http://localhost:21609/api/deliveryitems/InsertIntoPPTData/serNum77;tx2;siteNum2;bla2.xml;ppt_user2;tx_memo2;file_beg2;file_end2</td>
</tr>
<tr>
<th>Physical Path</th>
<td> C:/project/git/CStore/HHS.API/api/deliveryitems/InsertIntoPPTData/serNum77;tx2;siteNum2;bla2.xml;ppt_user2;tx_memo2;file_beg2;file_end2</td>
</tr>
<tr class="alt">
<th>Logon Method</th>
<td> Anonymous</td>
</tr>
<tr>
<th>Logon User</th>
<td> Anonymous</td>
</tr>
<tr class="alt">
<th>Request Tracing Directory</th>
<td> C:/Users/clay/Documents/IISExpress/TraceLogFiles/HHS.API</td>
</tr>
</table>
<div class="clear"></div>
</div>
</fieldset>
</div>
<div class="content-container">
<fieldset>
<h4>More Information:</h4>
This error means that the file or directory does not exist on the server. Create the file or directory and try the request again.
<p>
<a href="http://go.microsoft.com/fwlink/?LinkID=62293&IIS70Error=404,0,0x80070002,7601">View more information »</a>
</p>
</fieldset>
</div>
</div>
</body>
</html>
¡Que demonios!
Tristemente, sonriendo recuerdo que siempre hay una gárgola más escondida detrás de la cortina (donde Robinson Jeffers y Edgar Allen Poe aparentemente están luchando). Palely vagabundeando ...
ACTUALIZACIÓN 5
De acuerdo, aquí se dice de manera diferente:
De cartero, si uso esta URL:
http://localhost:21609/api/department/getndeptsfromid/2/12/
Lo hago en este método:
[HttpGet]
[Route("api/department/getndeptsfromid/{firstId}/{countToFetch}")]
public List<Department> GetNDepartmentsFromID(int FirstId, int CountToFetch)
{
return HHSService.GetNDepartmentsFromID(FirstId, CountToFetch);
}
... donde el valor de FirstId es 2, y el valor de CountToFetch es 12 (como yo esperaría que fueran). Pero luego, el cartero devuelve mi paquete con la anotación " 500 Sin valor para uno o más parámetros requeridos " .
¡Que demonios! ¡Ambos parámetros fueron aprobados obviamente!
Si utilizo un URI que parecería más correcto:
http://localhost:21609/api/department/getndeptsfromid?firstId=2&countToFetch=12
Yo obtengo:
{
Message: "No HTTP resource was found that matches the request URI
''http://localhost:21609/api/department/getndeptsfromid?firstId=2&countToFetch=12''."
MessageDetail: "No action was found on the controller ''Department'' that matches the request."
}
Sin embargo, esta es la ruta que he proporcionado:
[Route("api/department/getndeptsfromid/{firstId}/{countToFetch}")]
... y entonces diría que, de hecho, proporcioné una acción de coincidencia en el controlador. Y, por cierto, si simplemente introduzco esto como el URI en el cartero:
http://localhost:21609/api/department/getndeptsfromid
... y luego use la interfaz de "Valor / clave de parámetro de URL" de Postman para agregarlas, genera exactamente la misma URL que la anterior, como se puede ver aquí:
... y con exactamente el mismo resultado.
Solo puedo decirlo de nuevo (disculpe mi español inspirado en " Las Uvas de la Ira "): ¡Que demonios!
WebApiConfig.Register(GlobalConfiguration.Configuration); should be on top.
Debe asignar la ruta única para especificar sus parámetros como elementos de consulta. En RouteConfig.cs (o WebApiConfig.cs) agregue:
config.Routes.MapHttpRoute(
name: "MyPagedQuery",
routeTemplate: "api/{controller}/{action}/{firstId}/{countToFetch}",
defaults: new { action = "GetNDepartmentsFromID" }
);
Sus problemas no tienen nada que ver con POST / GET, pero solo con cómo especificar parámetros en RouteAttribute. Para asegurar esto, agregué soporte para ambos verbos en mis muestras.
Volvamos a dos ejemplos de trabajo muy simples.
[Route("api/deliveryitems/{anyString}")]
[HttpGet, HttpPost]
public HttpResponseMessage GetDeliveryItemsOne(string anyString)
{
return Request.CreateResponse<string>(HttpStatusCode.OK, anyString);
}
Y
[Route("api/deliveryitems")]
[HttpGet, HttpPost]
public HttpResponseMessage GetDeliveryItemsTwo(string anyString = "default")
{
return Request.CreateResponse<string>(HttpStatusCode.OK, anyString);
}
La primera muestra dice que "anyString" es un parámetro de segmento de ruta (parte de la URL).
El primer ejemplo de URL es:
- localhost: xxx / api / deliveryItems / dkjd; dslkf; dfk; kkklm; oeop
- return "dkjd; dslkf; dfk; kkklm; oeop"
La segunda muestra dice que "anyString" es un parámetro de cadena de consulta (opcional aquí ya que se ha proporcionado un valor predeterminado, pero puede hacerlo no opcional simplemente eliminando el valor predeterminado).
El segundo ejemplo de muestra URL son:
- localhost: xxx / api / deliveryItems? anyString = dkjd; dslkf; dfk; kkklm; oeop
- return "dkjd; dslkf; dfk; kkklm; oeop"
- localhost: xxx / api / deliveryItems
- devuelve "predeterminado"
Por supuesto, puede hacerlo aún más complejo como con esta tercera muestra:
[Route("api/deliveryitems")]
[HttpGet, HttpPost]
public HttpResponseMessage GetDeliveryItemsThree(string anyString, string anotherString = "anotherDefault")
{
return Request.CreateResponse<string>(HttpStatusCode.OK, anyString + "||" + anotherString);
}
Los ejemplos de la tercera URL son:
- localhost: xxx / api / deliveryItems? anyString = dkjd; dslkf; dfk; kkklm; oeop
- return "dkjd; dslkf; dfk; kkklm; oeop || anotherDefault"
- localhost: xxx / api / deliveryItems
- devuelve "No se encontró ningún recurso HTTP que coincida con el URI de solicitud ..." (el parámetro anyString es obligatorio)
- localhost: xxx / api / deliveryItems? anotherString = bluberb & anyString = dkjd; dslkf; dfk; kkklm; oeop
- devuelve "dkjd; dslkf; dfk; kkklm; oeop || bluberb"
- tenga en cuenta que los parámetros se han invertido, no importa, esto no es posible con "URL-style" del primer ejemplo
¿Cuándo debería usar el segmento de ruta o los parámetros de consulta? Algunos consejos ya han sido dados aquí: API REST Mejores prácticas: ¿Dónde poner parámetros?
¿Ha intentado usar el atributo [FromUri]
al enviar parámetros sobre la cadena de consulta?
Aquí hay un ejemplo:
[HttpGet]
[Route("api/department/getndeptsfromid")]
public List<Department> GetNDepartmentsFromID([FromUri]int FirstId, [FromUri] int CountToFetch)
{
return HHSService.GetNDepartmentsFromID(FirstId, CountToFetch);
}
Incluya este paquete en la parte superior también, using System.Web.Http;