usar net mvc metodo llamar examples example desde consumir como asp c# jquery ajax rest controller

mvc - jquery ajax asp.net c# example



¿Por qué mi método REST no es invocado por este jQuery? (5)

Solo le está dando a su jQuery los nombres de controlador y acción cuando necesita la url completa para completar la solicitud. Además, su punto final tiene un prefijo ''api''. Necesita que su propiedad url sea algo como http: // localhost : {puerto} / api / {controlador} / {acción} si su servidor se está ejecutando localmente.

Tengo una pregunta similar acerca de que el código del controlador de clic del botón jQuery no se dispare en absoluto aquí .

En este caso, se está disparando (cuando jQuery se agrega a una página estática (Index.cshtml)), pero mi método REST todavía no se está alcanzando. El mensaje de la consola que explica por qué es:

The resource cannot be found. Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly. Requested URL: /LandingPage/GetQuadrantData Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.6.1055.0

Esta es la jQuery, que de hecho se dispara cuando se hace clic en el botón, pero la llamada REST no se está realizando:

<script> $(function () { var btnGetData = document.getElementById(''btnGetData''); btnGetData.addEventListener("click", function () { alert("It works"); var unitval = ''ABUELOS''; var begdateval = ''2016-08-07''; var enddateval = ''2016-08-13''; $.ajax({ type: ''GET'', url: ''@Url.Action("GetQuadrantData", "LandingPage")'', data: { unit: unitval, begdate: begdateval, enddate: enddateval }, contentType: ''application/json'', cache: false, success: function (returneddata) { }, error: function () { alert(''hey, boo-boo!''); } }); }); }); </script>

El método REST está configurado así, en LandingPageController.cs:

[Route("{unit}/{begdate}/{enddate}")] public HttpResponseMessage GetQuadrantData(string unit, string begdate, string enddate) { _unit = unit; _beginDate = begdate; _endDate = enddate; . . .

Tengo un punto de interrupción en "_unit = unit"; línea, pero no se está alcanzando; ¿Por qué no? ¿Que me estoy perdiendo aqui?

La clase de controlador REST en discusión comienza así:

[RoutePrefix("api")] public class LandingPageController : ApiController

Nota: Si uso esto en jQuery ("Controlador" adjunto):

url: ''@Url.Action("GetQuadrantData", "LandingPageController")''

... tanto "GetQuadrantData" como "LandingPageController" están en rojo en el editor IDE (Visual Studio); las letras son rojas.

OTOH, si uso esto (sin el "Controlador" adjunto):

url: ''@Url.Action("GetQuadrantData", "LandingPage")''

(que me ha funcionado en el pasado, dejando el "Controlador" fuera del nombre del Controlador), tanto "GetQuadrantData" como "LandingPage" están SUBLINADOS en rojo, pero la fuente sigue siendo del color normal.

ACTUALIZAR

Usando el enlace de Nico en su comentario a continuación, cambié la línea jQuery "url" a esto:

url: ''@Url.Action("GetQuadrantData", "LandingPage", new { httproute = "" })'',

... pero aún no hizo que se alcanzara el método del Controlador.

ACTUALIZACIÓN 2

Al recorrer el javascript en el navegador (Chrome), veo que la línea "url" se ha cambiado dinámicamente de lo que es en el momento del diseño:

url: ''@Url.Action("GetQuadrantData", "LandingPage", new { httproute = "" })'',

...a:

url: ''/api/LandingPage?action=GetQuadrantData'',

Creo que lo que realmente debería haberse resuelto es más como:

url: ''/api/ABUELOS/2016-08-14/2016-08-20'',

¿Estoy en lo cierto? ¿Por qué no se está resolviendo así?

Si ingreso manualmente esa URL en el navegador, de modo que la barra de URL http://localhost:52194/api/ABUELOS/2016-08-21/2016-08-27 " http://localhost:52194/api/ABUELOS/2016-08-21/2016-08-27 " funciona: se llega al método y "hace lo suyo".

ACTUALIZACIÓN 3

Intenté esto también:

$(function () { $("#btnGetData").click(function () { document.body.style.cursor = ''wait''; $.ajax({ type: "GET", url: ''@Url.Action("GetQuadrantData", "LandingPage")'', success: function (retval) { $("body").append($(retval)); document.body.style.cursor = ''pointer''; }, error: function () { alert(''error in btnGetData''); } }); // end AJAX }); // end click }); // end ready function

... pero solo vio "error en btnGetData"

ACTUALIZACIÓN 4

Mi error más reciente es este:

$("#btnGetData").click(function () { document.body.style.cursor = ''wait''; var unitval = $(''#unitName'').val(); var begdateval = $(''#datepickerFrom'').val(); var enddateval = $(''#datepickerTo'').val(); $.ajax({ type: ''GET'', url: ''@Url.Action("GetQuadrantData", "LandingPage")'', data: { unit: unitval, begdate: begdateval, enddate: enddateval }, cache: false, success: function (returneddata) { alert($(returneddata)); }, error: function () { alert(''error in ajax''); } }); });

De nuevo, solo veo "error en ajax"

ACTUALIZACIÓN 5

Nota : La recompensa máxima (200 puntos, creo que es) se otorgará a quien pueda resolver este dilema. Si lo hace más de una persona, la recompensa recae en quien la resuelva mejor (lo que básicamente para mí significa de la manera más directa y fácil de implementar).

En aras de la revelación total y la desesperación, aquí está todo el contenido (con partes aburridas / sin sentido eliminadas con puntos suspensivos) de la primera página que se muestra cuando se ejecuta la aplicación WEB API (desde / Views / Home / Index.cshtml:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>eServices Reporting - Customer Dashboard</title> <!-- Latest compiled and minified CSS --> <link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"> <!-- jQuery library --> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script> <!-- Latest compiled JavaScript --> <script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script> <!--[if IE]> <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <style> body { padding-top: 20px; padding-bottom: 20px; background-color: white; } . . . </style> <script> $(function () { $("#btnGetData").click(function () { document.body.style.cursor = ''wait''; var unitval = "ABUELOS"; //$(''#unitName'').val(); var begdateval = $(''#datepickerFrom'').val(); var enddateval = $(''#datepickerTo'').val(); $.ajax({ type: ''GET'', url: ''@Url.Action("GetQuadrantData", "LandingPage")'', data: { unit: unitval, begdate: begdateval, enddate: enddateval }, cache: false, success: function (returneddata) { alert($(returneddata)); }, error: function () { alert(''error in ajax''); } }); }); }); // end ready function </script> </head> <body> <div class="container body-content"> <div class="jumbotronjr"> <div class="col-md-3" style="margin-top: 0.6cm"> <img src="http://www.proactusa.com/wp-content/themes/proact/images/pa_logo_notag.png" height="86" width="133" alt="PRO*ACT usa logo"> </div> <div class="col-md-9"> <label class="titletext" style="margin-top: 0.2cm;">Customer Dashboard</label> <br /> <label class="titletextjr" style="margin-top: -2.2cm;" id="unitName">Craftworks</label> <label class="cccsfont"> for the week of August 14 </label> <input class="smalldatepicker" type="date" id="datepickerFrom" name="daterangefrom" value="2016-08-14"> </input> <label class="cccsfont"> to </label> <input type="date" class="smalldatepicker" id="datepickerTo" name="daterangeto" value="2016-08-20"> </input> <button class="btn green smallbutton" id="btnGetData" name="btnGetData">SUBMIT</button> </div> </div> <div class="row"> <div class="col-md-12"> <hr /> </div> </div> <div class="row"> <div class="col-md-12"> </div> </div> <div class="row"> <div class="col-md-6"> <div class="topleft"> <h2 class="sectiontext">Top 10 Items Purchased</h2> <table> <tr> <th>Item Code</th> <th>Description</th> <th class="rightjustifytext">Qty</th> </tr> <tr> <td>101200</td> <td>ASPARAGUS, STANDARD 11/1#</td> <td class="rightjustifytext">32</td> </tr> <tr> <td>140200</td> <td>MUSHROOMS, MEDIUM 10#</td> <td class="rightjustifytext">20</td> </tr> <tr> <td>140000</td> <td>MUSHROOMS, BUTTON 10#</td> <td class="rightjustifytext">14</td> </tr> <tr> <td>127100</td> <td>LETTUCE, ROMAINE 24 CT </td> <td class="rightjustifytext">14</td> </tr> <tr> <td>300123</td> <td>BEANS, GREEN TRIM 2/5# (BAGS)</td> <td class="rightjustifytext">13</td> </tr> <tr> <td>173100</td> <td>POTATOES, 50 CT IDAHO</td> <td class="rightjustifytext">12</td> </tr> <tr> <td>234225</td> <td>BERRIES, STRAWBERRY 1# CLAM</td> <td class="rightjustifytext">11</td> </tr> <tr> <td>188500</td> <td>TOMATOES, GRAPE 12/1 PT</td> <td class="rightjustifytext">10</td> </tr> <tr> <td>122500</td> <td>LETTUCE, ICEBERG LINER 24 CT</td> <td class="rightjustifytext">10</td> </tr> <tr> <td>121050</td> <td>LETTUCE, GREEN LEAF 24 CT</td> <td class="rightjustifytext">10</td> </tr> </table> </div> </div> <div class="col-md-6"> <div class="topright"> <h2 class="sectiontext">Pricing Exceptions - Weekly Recap</h2> <label class="redfont cccs">Red denotes Contract Item Overages</label> </br> <label class="cccs">For Weyand on the pricing week of - 7/31/2016</label> <table> <tr> <th>PRO*ACT Member</th> <th class="rightjustifytext">Total Occurrences of Summary Items</th> <th class="rightjustifytext">Total Summary Exceptions</th> <th class="rightjustifytext">Total Percentage of Summary Exceptions</th> </tr> <tr> <td style="width:30%">Stern</td> <td style="width:23%" class="rightjustifytext">205</td> <td style="width:23%" class="rightjustifytext">2</td> <td style="width:24%" class="rightjustifytext">99.02%</td> </tr> <tr> <td>Hardies Dallas</td> <td class="rightjustifytext">1,597</td> <td class="rightjustifytext">0</td> <td class="rightjustifytext">100.00%</td> </tr> <tr> <td>Hardies South</td> <td class="rightjustifytext">612</td> <td class="rightjustifytext">1</td> <td class="rightjustifytext">99.84%</td> </tr> <tr> <td>Go Fresh</td> <td class="rightjustifytext">482</td> <td class="rightjustifytext">0</td> <td class="rightjustifytext">100.00%</td> </tr> <tr> <td>Segovias</td> <td class="rightjustifytext">1,360</td> <td class="rightjustifytext">2</td> <td class="rightjustifytext">99.85%</td> </tr> <tr> <td>Potato Spec</td> <td class="rightjustifytext">1,605</td> <td class="rightjustifytext">0</td> <td class="rightjustifytext">100.00%</td> </tr> <tr> <td class="rightjustifytext bold">TOTAL</td> <td class="rightjustifytext bold">5,861</td> <td class="rightjustifytext bold">5</td> <td class="rightjustifytext bold">99.79%</td> </tr> </table> </div> </div> </div> <div class="row"> <div class="col-md-6"> <div class="bottomleft"> <h2 class="sectiontext">Forecasted Spend - $9,814.81</h2> <table> <tr> <th>Item Code</th> <th class="rightjustifytext">Last Week''s Usage</th> <th class="rightjustifytext">This Week''s Price</th> <th class="rightjustifytext">Forecasted Spend</th> </tr> <tr> <td>261650</td> <td class="rightjustifytext">49</td> <td class="rightjustifytext">3.14</td> <td class="rightjustifytext">153.86</td> </tr> <tr> <td>231083</td> <td class="rightjustifytext">52</td> <td class="rightjustifytext">1.25</td> <td class="rightjustifytext">65.00</td> </tr> <tr> <td>398980</td> <td class="rightjustifytext">46</td> <td class="rightjustifytext">4.95</td> <td class="rightjustifytext">227.70</td> </tr> <tr> <td>351135</td> <td class="rightjustifytext">40</td> <td class="rightjustifytext">0.75</td> <td class="rightjustifytext">30.00</td> </tr> <tr> <td>398036</td> <td class="rightjustifytext">42</td> <td class="rightjustifytext">3.00</td> <td class="rightjustifytext">126.00</td> </tr> <tr> <td>208110</td> <td class="rightjustifytext">42</td> <td class="rightjustifytext">2.50</td> <td class="rightjustifytext">105.00</td> </tr> <tr> <td>102800</td> <td class="rightjustifytext">1835</td> <td class="rightjustifytext">2.25</td> <td class="rightjustifytext">4,128.75</td> </tr> <tr> <td>367050</td> <td class="rightjustifytext">1910</td> <td class="rightjustifytext">1.95</td> <td class="rightjustifytext">3,724.50</td> </tr> <tr> <td>173100</td> <td class="rightjustifytext">66</td> <td class="rightjustifytext">19.00</td> <td class="rightjustifytext">1,254.00</td> </tr> <tr> <td class="bold">TOTAL</td> <td class="bold rightjustifytext">4082</td> <td class="bold rightjustifytext">--</td> <td class="bold rightjustifytext">$9,814.81</td> </tr> </table> </div> </div> <div class="col-md-6"> <div class="bottomright"> <h2 class="sectiontext">Delivery Performance</h2> <table> <tr> <th>PRO*ACT Distributor</th> <th>Restaurant Location</th> <th class="rightjustifytext">Avg Order Amount</th> <th class="rightjustifytext">Avg Package Count</th> <th class="rightjustifytext">Total Sales</th> </tr> <tr> <td>Sunrise FL</td> <td>A1A ALEWORKS - #4405 - ST. AUGUSTINE</td> <td class="rightjustifytext">$475.78</td> <td class="rightjustifytext">28.50</td> <td class="rightjustifytext">$1,903.10</td> </tr> <tr> <td>Sunrise FL</td> <td>RAGTIME TAVERN - #4404 - ATLANTIC BEACH</td> <td class="rightjustifytext">$221.46</td> <td class="rightjustifytext">17.50</td> <td class="rightjustifytext">$885.82</td> </tr> <tr> <td>Sunrise FL</td> <td>SEVEN BRIDGES - #4403 - JACKSONVILLE</td> <td class="rightjustifytext">$367.49</td> <td class="rightjustifytext">22.67</td> <td class="rightjustifytext">$1,102.47</td> </tr> <tr> <td>T&T</td> <td>BIG RIVER - #4201 - CHATTANOOGA</td> <td class="rightjustifytext">$396.06</td> <td class="rightjustifytext">22.83</td> <td class="rightjustifytext">$2,376.34</td> </tr> <tr> <td>T&T</td> <td>BIG RIVER - #4205 - HAMILTON PL</td> <td class="rightjustifytext">$424.74</td> <td class="rightjustifytext">26.00</td> <td class="rightjustifytext">$1,698.95</td> </tr> <tr> <td class="bold">TOTAL</td> <td></td> <td class="bold rightjustifytext">3,770.42</td> <td class="bold rightjustifytext">23.50</td> <td class="bold rightjustifytext">$1,592.60</td> </tr> </table> </div> </div> </div> </div> </body> </html>

ACTUALIZACIÓN 6

Sé que hay más en la respuesta de Arturo que esto, pero hasta ahora simplemente agregué esto:

config.Routes.MapHttpRoute( name: "QuadrantData", routeTemplate: "api/{unit}/{begdate}/{enddate}" );

... ha ayudado, ya que se está alcanzando el punto de corte en mi método. Desafortunadamente, grazna "SyntaxError: token inesperado <en JSON en la posición 0"


En cuanto a tu punto:

Si ingreso manualmente esa URL en el navegador, de modo que la barra de URL muestre " http: // localhost: 52194 / api / ABUELOS / 2016-08-21 / 2016-08-27 " funciona: se llega al método y "hace lo suyo".

La modificación de su llamada Ajax como se muestra a continuación debería resolver su problema y enviará una solicitud GET a la url mapeada (se muestra con el controlador de evento click click ):

$("#btnGetData").click(function () { var unitval = ''ABUELOS''; var begdateval = ''2016-08-21''; var enddateval = ''2016-08-27''; $.getJSON("api/" + unitval + "/" + begdateval + "/" + enddateval, function (Data) { // do what ever you want with the success response }) .fail( function (jqXHR, textStatus, err) { // do what ever you want with the failed response }); });


Personalmente, no soy un gran admirador de usar @ Url.Action en el código de JavaScript; así es como hago llamadas ajax:

  • Cree un campo oculto en la página de diseño para almacenar la URL raíz - <input type="hidden" id="hdnRoot" value="@Url.Content("~/")" />
  • Tener un archivo constants json para mantener mis constantes del lado del cliente (constants.js) - asigna el valor del campo oculto a la variable serviceRoot :

    (function () { window.constants = { serviceRoot: $("#hdnRoot").val() + "api/", objectState: { added: "Added", modified: "Modified", unchanged: "Unchanged", deleted: "Deleted" }, ..other values... }; })();

  • Modificará su llamada ajax como:

    var root = window.constants.serviceRoot; $.ajax({ type: ''GET'', url: root + ''LandingPage/GetQuadrantData/''+unitval+''/''+begdateval+''/''+enddateval, // data: { unit: unitval, begdate: begdateval, enddate: enddateval }, contentType: ''application/json'', cache: false, success: function (returneddata) { }, error: function () { alert(''hey, boo-boo!''); } }); [RoutePrefix("api")] public class LandingPageController : ApiController { [HttpGet] [Route("GetQuadrantData/{unit}/{begdate}/{enddate}", Name="GetQuadrantDataFromLandingPage")] public HttpResponseMessage GetQuadrantData(string unit, string begdate, string enddate)


Ok, esta solución resuelve tu problema pero implica algunos cambios en tu código:

En la vista, cuando llamas a Url.Action , tratas de generar una ruta webapi desde un controlador mvc. Puedes ver esta pregunta donde digo cómo hacer esto.

Básicamente, la idea es usar Url.RouteUrl con un valor de ruta adicional httproute = true .

Ahora, necesita cambiar algunas partes en su código para poder usar esto:

En primer lugar, está utilizando atributos para definir sus rutas API web, por lo tanto, estas rutas se agregarán después de las rutas definidas en su clase WebApiConfig , y como mencioné en la respuesta de la pregunta referenciada, Url.RouteUrl devolverá la primera ruta que coincida los valores de ruta. Por lo tanto, debe declarar la ruta en WebApiConfig antes de la ruta predeterminada:

/* attributes removed */ public class LandingPageController : ApiController { public HttpResponseMessage GetQuadrantData(string unit, string begdate, string enddate) { ... public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.MapHttpAttributeRoutes(); /* Route added before the default one */ config.Routes.MapHttpRoute( name: "QuadrantData", routeTemplate: "api/{unit}/{begdate}/{enddate}" ); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); } }

Si no lo hace, la ruta predeterminada se combinará, ya que {id} es opcional y unit , begdate y enddate se pasarán como parámetros de consulta.

Una vez resuelto este problema, tiene otro problema, para poder usar Url.RouteUrl necesita conocer todos los valores de ruta (unit, begdate, enddate), que están disponibles solo cuando se ejecuta la función de script. Pero todo el código de afeitar en su .cshtml se procesa en el servidor cuando se genera el html para el cliente.

Como puede ver, cuando se ejecuta el javascript, no está ejecutando ''@Url.RouteUrl...'' o ''@Url.Action...'' , en este momento solo está manejando una cadena con valor devuelto cuando la expresión de razuradora Fue procesado.

Una cosa que puede hacer es pasar los valores de "plantilla" a la llamada Url.RouteUrl y reemplazarla cuando la secuencia de comandos se ejecuta con los valores reales:

var url = ''@Url.RouteUrl(new { unit = "(unit)", begdate = "(begdate)", enddate = "(enddate)", httproute = true })'' url = url.replace("(unit)", unitval) .replace("(begdate)", begdateval) .replace("(enddate)", enddateval) $.ajax({ type: ''GET'', url: url, contentType: ''application/json'', cache: false, success: function (returneddata) { }, error: function () { alert(''hey, boo-boo!''); } });

Después de replace s, el valor de la url variable será como este /api/ABUELOS/2016-08-07/2016-08-13 .

Si no desea mover las rutas a WebApiConfig , puede establecer un nombre en RouteAttribute :

[RoutePrefix("api")] public class LandingPageController : ApiController { [Route("{unit}/{begdate}/{enddate}", Name = "QuadrantData")] public HttpResponseMessage GetQuadrantData(string unit, string begdate, string enddate) { ...

Y especifique el nombre de la ruta en la llamada Url.RouteUrl :

var url = ''@Url.RouteUrl("QuadrantData", new { unit = "(unit)", begdate = "(begdate)", enddate = "(enddate)", httproute = true })''

De esta manera es menos intrusivo en su código, pero necesita saber el nombre de la ruta que desea usar.

Espero que esto ayude.


Tiene algunos problemas con la forma en que está generando la ruta y la forma en que intenta acceder a ella.

La acción de la API web usa el enrutamiento de atributos, por lo que, de forma predeterminada, no hay un nombre de ruta para que coincida, como en el enrutamiento basado en la convención.

Actualice el atributo de ruta para incluir un nombre para encontrar en la tabla de rutas.

[RoutePrefix("api")] public class LandingPageController : ApiController { [HttpGet] [Route("{unit}/{begdate}/{enddate}", Name="QuadrantData")] public HttpResponseMessage GetQuadrantData(string unit, string begdate, string enddate) { _unit = unit; _beginDate = begdate; _endDate = enddate; //...other code } //...other code }

Luego, aunque tengas el nombre, también debes incluir los parámetros de la plantilla para obtener una coincidencia de MVC y hacer que genere la url en la plantilla que definiste en la acción.

Para generar un enlace a la API web, se vería así

@Url.RouteUrl(routeName : "QuadrantData", routeValues : new { httpRoute = true , unit = "ABUELOS", begdate = "2016-08-07", enddate = "2016-08-13" })

o

@Url.HttpRouteUrl(routeName : "QuadrantData", routeValues : new { unit = "ABUELOS", begdate = "2016-08-07", enddate = "2016-08-13" })

que agregaría el httpRoute a los valores de ruta.

Referencia: construcción de URL a la vista de la API web con enrutamiento de atributos

Ahora, con su enfoque fuera del camino, sugeriría el siguiente enfoque alternativo.

Principio de KISS Cambie el punto final de la API web (REST) ​​a POST y cambie su plantilla.

[RoutePrefix("api")] public class LandingPageController : ApiController { //eg POST api/QuadrantData [HttpPost] [Route("QuadrantData", Name="GenerateQuadrantData")] public HttpResponseMessage QuadrantData(string unit, string begdate, string enddate) { _unit = unit; _beginDate = begdate; _endDate = enddate; //...other code } //...other code }

y enviar los datos en el cuerpo de una solicitud JSON POST

$(function () { $("#btnGetData").click(function () { document.body.style.cursor = ''wait''; var unitval = "ABUELOS"; //$(''#unitName'').val(); var begdateval = $(''#datepickerFrom'').val(); var enddateval = $(''#datepickerTo'').val(); var jsonBody = JSON.stringify({ unit: unitval, begdate: begdateval, enddate: enddateval }); $.ajax({ type: ''POST'', url: ''@Url.HttpRouteUrl("GenerateQuadrantData", null)'', contentType: ''application/json'', dataType: ''json'', data: jsonBody, cache: false, success: function (returneddata) { alert($(returneddata)); }, error: function () { alert(''error in ajax''); } }); }); }); // end ready function