jquery con ASP.NET MVC – llamando al servicio web habilitado ajax

Esto es un poco una continuación de una pregunta anterior .

Ahora estoy tratando de hacer una llamada a un servicio web habilitado para AJAX que he definido dentro de la aplicación ASP.NET MVC (es decir, MovieService.svc ). Pero el servicio nunca se llama en mi función getMovies javascript.

Esta misma técnica de llamar al servicio web AJAX funciona bien si lo bash en una aplicación ASP.NET MVC, por lo que me pregunto si las rutas ASP MVC pueden interferir de algún modo cuando intenta hacer que el servicio web AJAX llame .

¿Tiene alguna idea de por qué no se llama a mi servicio web? Código a continuación.

  <script src="" type="text/javascript"> <script src="" type="text/javascript"> <script src="" type="text/javascript"> <script src="" type="text/javascript">  var lastsel2; function successFunction(jsondata) { debugger var thegrid = jQuery("#editgrid"); for (var i = 0; i < jsondata.d.length; i++) { thegrid.addRowData(i + 1, jsondata.d[i]); } } function getMovies() { debugger // ***** the MovieService#GetMovies method never gets called $.ajax({ url: 'MovieService.svc/GetMovies', data: "{}", // For empty input data use "{}", dataType: "json", type: "GET", contentType: "application/json; charset=utf-8", success: successFunction }); } jQuery(document).ready(function() { jQuery("#editgrid").jqGrid({ datatype: getMovies, colNames: ['id', 'Movie Name', 'Directed By', 'Release Date', 'IMDB Rating', 'Plot', 'ImageURL'], colModel: [ { name: 'id', index: 'Id', width: 55, sortable: false, hidden: true, editable: false, editoptions: { readonly: true, size: 10} }, { name: 'Movie Name', index: 'Name', width: 250, editable: true, editoptions: { size: 10} }, { name: 'Directed By', index: 'Director', width: 250, align: 'right', editable: true, editoptions: { size: 10} }, { name: 'Release Date', index: 'ReleaseDate', width: 100, align: 'right', editable: true, editoptions: { size: 10} }, { name: 'IMDB Rating', index: 'IMDBUserRating', width: 100, align: 'right', editable: true, editoptions: { size: 10} }, { name: 'Plot', index: 'Plot', width: 150, hidden: false, editable: true, editoptions: { size: 30} }, { name: 'ImageURL', index: 'ImageURL', width: 55, hidden: true, editable: false, editoptions: { readonly: true, size: 10} } ], pager: jQuery('#pager'), rowNum: 5, rowList: [5, 10, 20], sortname: 'id', sortorder: "desc", height: '100%', width: '100%', viewrecords: true, imgpath: '/Content/jqGridCss/redmond/images', caption: 'Movies from 2008', editurl: '/Home/EditMovieData/', caption: 'Movie List' }); $("#bedata").click(function() { var gr = jQuery("#editgrid").jqGrid('getGridParam', 'selrow'); if (gr != null) jQuery("#editgrid").jqGrid('editGridRow', gr, { height: 280, reloadAfterSubmit: false }); else alert("Hey dork, please select a row"); }); });  

To learn more about ASP.NET MVC visit http://asp.net/mvc.

Aquí está mi código de RegisterRoutes:

 public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.IgnoreRoute("*MovieService.svc*"); routes.MapRoute( "Default", // Route name "{controller}/{action}/{id}", // URL with parameters new { controller = "Home", action = "Index", id = "" } // Parameter defaults ); } 

Así es como se ve mi clase de MovieService:

 namespace jQueryMVC { [ServiceContract(Namespace = "")] [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] public class MovieService { // Add [WebGet] attribute to use HTTP GET [OperationContract] [WebGet(ResponseFormat = WebMessageFormat.Json)] public IList GetMovies() { return Persistence.GetMovies(); } } } 

Su problema principal es que utiliza URL no absolutas en la llamada ajax . Las entradas incorrectas en web.config también pueden causar problemas. Además, utiliza datatype: getMovies lugar de datatype: 'json' y postData: yourData . El camino con el datatype como funciones existe (ver http://www.trirand.com/jqgridwiki/doku.php?id=wiki:retrieving_data#function ), pero desde jqGrid 3.6.5 tienes un camino más directo dentro de jsonReader para leer los datos devueltos del servidor web.

ACTUALIZADO: me parece que describiré las funciones de edición que haré más adelante y explicaré aquí cómo obtener datos JSON y cómo llenarlos dentro de jqGrid.

En primer lugar, jqGrid puede solicitar los datos JSON del servidor. Por lo tanto, no es necesario que hagamos una llamada jQuery.ajax separado. Solo necesita definir una URL que apunte al servidor y definir algunos parámetros jQuery.ajax adicionales que prefiera. No publica en su pregunta la definición de la clase Movie . Así que lo defino yo mismo como si fuera

 public class Movie { public int Id { get; set; } public string Name { get; set; } public string Director { get; set; } public string ReleaseDate { get; set; } public string IMDBUserRating { get; set; } public string Plot { get; set; } public string ImageURL { get; set; } } 

Debería comentar que Microsoft serializa el tipo DataTime no como una cadena de fecha legible, sino como una cadena /Date(utcDate)/ , donde utcDate es este número (consulte jQuery.param () – ¿no serializa los objetos Date de JavaScript? ). Para hacer menos problemas al comienzo, defino ReleaseDate como cadena.

Método IList GetMovies() devuelve datos JSON como una matriz de objetos Movie . Entonces, jqGrid como respuesta a la solicitud HTTP GET recibe de la URL MovieService.svc/GetMovies los datos siguientes:

  [{"Id":1, "Name": "ET", "Director": "Steven Spielberg",...},{...},...] 

Puedo decir que no es un formato típico de datos, que están esperando jqGrid (compáralo con http://www.trirand.com/jqgridwiki/doku.php?id=wiki:retrieving_data#json_data ). Para poder ubicar los datos dentro de jqGrid, debemos definir un jsonReader . Entonces hacemos lo siguiente

 jQuery("#editgrid").jqGrid({ url: '< %= Url.Content("~/MovieService.svc/GetMovies")%>', datatype: 'json', ajaxGridOptions: { contentType: "application/json" }, jsonReader: { repeatitems: false, id: "Id", root: function(obj) { return obj; }}, headertitles: true, sortable: true, colNames: ['Movie Name', 'Directed By', 'Release Date', 'IMDB Rating', 'Plot', 'ImageURL'], colModel: [ { name: 'Name', width: 250}, { name: 'Director', width: 250, align: 'right' }, { name: 'ReleaseDate', width: 100, align: 'right' }, { name: 'IMDBUserRating', width: 100, align: 'right' }, { name: 'Plot', width: 150 }, { name: 'ImageURL', width: 55, hidden: true } ], pager: jQuery('#pager'), pginput: false, rowNum: 0, height: '100%', viewrecords: true, rownumbers: true, caption: 'Movies from 2008' }).jqGrid('navGrid', '#pager', { add: false, edit: false, del: false, search: false }); 

OBSERVACIÓN : eliminé del ejemplo los parámetros de ordenamiento, porque en caso de solicitud de datos JSON, el parámetro de clasificación se enviará únicamente al servidor (algunos parámetros adicionales añaden el URL del servidor) y el servidor debe devolver los datos ordenados. Para obtener más información, consulte la descripción del parámetro prmNames en http://www.trirand.com/jqgridwiki/doku.php?id=wiki:options y la descripción del parámetro sopt en http://www.trirand.com/jqgridwiki/doku. php? id = wiki: singe_searching .

Con respecto al datatype: 'json' de datatype: 'json' definimos dataType: 'json' parámetro dataType: 'json' de jQuery.ajax (no confunda el caso dentro del parámetro datatype ). Los nombres de todos los campos dentro de colModel definimos exactamente lo mismo que los nombres de campo dentro de nuestros objetos JSON. Algunos parámetros adicionales viewrecords , rownumbers , sortable y headertitles no son muy importantes en este ejemplo, elegí allí porque 1) me gusta allí y 2) configuré rowNum: 0 para hacer posible las opciones rownumbers: true funciona correcto y no nos muestra negativo los números de fila comenzaron con -5 si rowNum: 5 gusta en su ejemplo original.

Con ajaxGridOptions: { contentType: "application/json" } definimos parámetros adicionales que se reenviarán directamente a jQuery.ajax .

La parte más compleja de este ejemplo es

 jsonReader: { repeatitems: false, id: "Id", root: function(obj) { return obj; }} 

Define que la identificación de todas las filas tiene el nombre “Id” (ver definición de la class Movie ). ” repeatitems: falserepeatitems: false que cada campo de datos que queremos identificar por el nombre del campo (definido en colModel ) en lugar de la definición predeterminada por posición. La definición de root es un poco extraña, pero define cómo encontrar la raíz de las filas dentro de los datos JSON. El formato predeterminado de los datos JSON está siguiendo

 { total: "xxx", page: "yyy", records: "zzz", rows : [ {id:"1", cell:["cell11", "cell12", "cell13"]}, {id:"2", cell:["cell21", "cell22", "cell23"]}, ... ] } 

y la raíz de las filas se define como root: "rows" . Entonces, si los datos JSON asignados a la variable res , la raíz se puede devolver como res.rows . Para permitir que jqGrid lea nuestros datos, definimos jsonReader.root como una función (esta característica existe ya que jqGrid 3.6.5 ver http://www.trirand.com/jqgridwiki/doku.php?id=wiki:change#additions_and_changes ). Puedes verificar que este extraño método funcione. La page parámetros adicionales típicos, el total ( lastpage ) y los records no existen dentro de nuestros datos JSON y se inicializarán como la page:0, total:1, records:0 siguiente page:0, total:1, records:0 . Entonces no podemos hacer paginación de datos. Puede expandir jsonReader con funciones que definen la page , el total y los records (también como funciones) como

 jsonReader: { repeatitems: false, id: "Id", root: function (obj) { return obj; }, page: function (obj) { return 1; }, total: function (obj) { return 1; }, records: function (obj) { return obj.length; } } 

que completará nuestro jsonReader. Entonces el ajuste de rowNum: 0 no será más necesario.

Mostré esta manera solo para mostrar la flexibilidad de jqGrid. Debe usar la forma descrita solo si accede a un servidor web que no puede cambiar. jqGrid tiene características como paginación , clasificación y dos tipos de búsqueda (más como filtrado con DONDE en el SELECCIONAR correspondiente) de datos: simple y avanzado. Si queremos tener estas bonitas funciones dentro de jqGrid en nuestras páginas web, debemos definir en el servicio web un método adicional como

 [OperationContract] [WebGet(ResponseFormat = WebMessageFormat.Json, UriTemplate = "jqGridGetTestbereiche?_search={_search}&page={page}&"+ "rows={rows}&sidx={sortIndex}&sord={sortDirection}&"+ "searchField={searchField}&searchString={searchString}&"+ "searchOper={searchOper}&filters={filters}")] public jqGridTable jqGridGetMovies( int page, int rows, string sortIndex, string sortDirection, string _search, string searchField, string searchString, string searchOper, string filters) 

donde jqGridTable

 public class jqGridTable { public int total { get; set; } // total number of pages public int page { get; set; } // current zero based page number public int records { get; set; } // total number of records public List rows { get; set; } } public class jqGridRow { public string id { get; set; } public List cell { get; set; } } 

O si queremos utilizar la forma más compacta de datos transferidos de servidor a cliente, entonces

 // jsonReader: { repeatitems : true, cell:"", id: "0" } public class jqGridTable { public int total { get; set; } // total number of pages public int page { get; set; } // current zero based page number public int records { get; set; } // total number of records public List> rows { get; set; }// first element in every row must be id of row. } 

(Puede leer más sobre este tipo de transferencia de datos en http://www.trirand.com/blog/jqgrid/jqgrid.html si elige en la parte izquierda del árbol “Asignación de datos” y luego “Optimización de datos”)

PD: Acerca de jsonReader puedes leer más en http://www.trirand.com/jqgridwiki/doku.php?id=wiki:retrieving_data#json_data . Una de mis respuestas anteriores Mapear datos JSON en JQGrid también puede ser interesante para usted.

ACTUALIZADO 2 : Debido a que no marca la respuesta como aceptada, se queda con algunos problemas. Así que creé un nuevo proyecto en Visual Studio 2010 que demuestra lo que escribí. Puede descargar la fuente desde http://www.ok-soft-gmbh.com/jqGrid/jQueryMVC.zip . Compare con su proyecto, especialmente la parte con url completo como un parámetro de jqGrid y una parte de web.config que describe la interfaz de servicio WCF.

ACTUALIZADO 3 : uso VS2010 no hace tanto tiempo. Así que podría degradarlo rápidamente a VS2008. Así que casi el mismo código funciona en Visual Studio 2008, pero con ASP.NET MVC 2.0 puede descargar desde http://www.ok-soft-gmbh.com/jqGrid/VS2008jQueryMVC.zip . El código en ASP.NET MVC 1.0 debería ser el mismo, pero un GUID del archivo de proyecto y algunas cadenas de Web.config deberían tener parches (ver http://www.asp.net/learn/whitepapers/aspnet-mvc2- notas de actualización ).

Esto se debe a que la ruta registrada en el archivo global.asax no reconocerá este archivo .svc. intentará buscar ese controlador con la acción getmovies y fallará. prueba la depuración usando firebug. puedes solucionar esto ignorando esta ruta en el archivo global.asax

Me encontré con el mismo problema. Llegué a la conclusión de que las rutas interferían con la llamada de servicio. ¿Has probado Phil Haack’s Route Debugger ? Me salvó el tocino un par de veces.

Al final, creé un punto final en uno de los controladores.

Oleg,

¿Tiene el ejemplo del que estaba hablando cuando estoy trabajando con jqgrid / asp.net mvc y un servicio reparador y teniendo un problema de tiempo? Ayudaría a ver un ejemplo ya que estoy en una pared. Gracias

SEM