使用ASP.NET MVC的jquery – 调用启用了ajax的Web服务

这是前一个问题的一个延续。

现在我正在尝试调用我在ASP.NET MVC应用程序中定义的支持AJAX的Web服务(即MovieService.svc )。 但是我的getMovies javascript函数永远不会调用该服务。

如果我在非ASP.NET MVC应用程序中尝试,这种调用AJAX Web服务的技术工作正常,所以它让我想知道ASP MVC路由在尝试进行AJAX Web服务调用时是否会以某种方式干扰某些事情。

你知道为什么我的网络服务没有被调用吗? 代码如下。

  <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.

这是我的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 ); } 

这是我的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(); } } } 

您的主要问题是您在ajax调用中使用的不是绝对URL。 web.config错误条目也会产生问题。 此外,您使用datatype: getMovies而不是datatype: 'json'postData: yourDatadatatype作为函数的方式存在(参见http://www.trirand.com/jqgridwiki/doku.php?id=wiki:retrieving_data#function ),但是从jqGrid 3.6.5开始,你有更多直接的方法在jsonReader中读取从Web服务器返回的数据。

更新:在我看来,我将在稍后介绍编辑function,并在此解释如何获取JSON数据并填充jqGrid内部。

首先,jqGrid可以从服务器请求自己的JSON数据。 所以我们不需要单独进行jQuery.ajax调用。 您只需要定义一个指向服务器的URL,并定义一些您喜欢的其他jQuery.ajax参数。 您不会在您的问题中发布Movie类的定义。 所以我自己定义如下

 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; } } 

你应该注意到,微软序列化DataTime类型不是一个可读的日期字符串,而是一个字符串/Date(utcDate)/ ,其中utcDate是这个数字(参见jQuery.param() – 不序列化javascript Date对象? )。 为了在开始时减少问题,我将ReleaseDate定义为字符串。

方法IList GetMovies()返回JSON数据,就像对象数组Movie 。 所以jqGrid作为对HTTP GET请求的响应从MovieService.svc/GetMovies URL接收如下数据:

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

我可以说这不是典型的数据格式,它正在等待jqGrid(与http://www.trirand.com/jqgridwiki/doku.php?id=wiki:retrieving_data#json_data相比 )。 为了能够将数据放在jqGrid中,我们必须定义一个jsonReader 。 所以我们遵循

 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 }); 

备注 :我从示例中删除了任何排序参数,因为在请求JSON数据的情况下,排序参数将仅发送到服务器(一些附加参数附加服务器URL),服务器必须返回排序数据。 有关更多信息,请参阅http://www.trirand.com/jqgridwiki/doku.php?id=wiki:options上的prmNames参数说明以及http://www.trirand.com/jqgridwiki/doku上prmNames参数的说明。 php?id = wiki:singe_searching 。

关于datatype: 'json'我们定义jQuery.ajax dataType: 'json'参数(不要混淆datatype参数内的情况)。 我们定义的colModel中所有字段的名称与JSON对象中的字段名称完全相同 。 一些额外的参数viewrecordsrownumberssortableheadertitles在这个例子中不是很重要,我选择那里是因为1)我喜欢那里2)我设置rowNum: 0以使选项rownumbers: true成为可能rownumbers: true工作正确并且不显示负面行号以-5开头,如果是rowNum: 5就像在原始示例中一样。

使用ajaxGridOptions: { contentType: "application/json" }我们定义了将直接转发到jQuery.ajax其他参数。

这个例子中最复杂的部分是

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

它定义了所有行的id都具有名称“Id”(参见class Movie定义)。 “ repeatitems: false ”表示我们想要的每个数据字段都由字段名称(在colModel定义)而不是每个位置的默认定义。 root的定义有点奇怪,但是它定义了如何在JSON数据中找到 。 JSON数据的默认格式如下

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

并且行的根被定义为root: "rows" 。 因此,如果分配给变量res的JSON数据,则root可以作为res.rows返回。 为了允许jqGrid读取我们的数据,我们将jsonReader.root定义为一个函数(此function自jqGrid 3.6.5起见,请参阅http://www.trirand.com/jqgridwiki/doku.php?id=wiki:change#additions_and_changes )。 您可以validation这种奇怪的方法是否有效。 我们的JSON数据中不存在典型的附加参数pagetotallastpage )和records ,它们将初始化为以下page:0, total:1, records:0 。 所以我们无法进行数据分页。 您可以使用定义pagetotalrecords (也作为函数)的函数来扩展jsonReader

 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; } } 

这将完成我们的jsonReader。 然后不再需要设置rowNum: 0

我这样展示只是为了展示jqGrid的灵活性。 仅当您访问无法更改的Web服务器时,才应使用所描述的方法。 jqGrid具有分页排序和两种搜索function (更像是在相应的SELECT中使用WHERE进行过滤)的function:简单和高级。 如果我们想在我们的网页上的jqGrid中有这些不错的function,我们应该在Web Service中定义一个额外的方法

 [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) 

其中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; } } 

或者,如果我们想要使用从服务器传输到客户端的最紧凑的数据forms

 // 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. } 

(如果您在左侧树部分“数据映射”然后选择“数据优化”,您可以在http://www.trirand.com/blog/jqgrid/jqgrid.html上阅读有关此类数据传输的更多信息。)

PS:关于jsonReader,您可以在http://www.trirand.com/jqgridwiki/doku.php?id=wiki:retrieving_data#json_data上阅读更多内容。 我的一个老答案在JQGrid中映射JSON数据对您来说也很有趣。

更新2 :因为你没有把答案标记为已被接受,所以你留下了一些问题。 所以我在Visual Studio 2010中创建了一个新项目来演示我写的内容。 您可以从http://www.ok-soft-gmbh.com/jqGrid/jQueryMVC.zip下载源代码。 与您的项目进行比较,尤其是具有完整URL作为jqGrid参数的部分以及描述WCF服务接口的web.config的一部分。

更新3 :我使用VS2010的时间不长。 所以我可以很快将其降级到VS2008。 因此几乎相同的代码在Visual Studio 2008中工作,但是使用ASP.NET MVC 2.0,您可以从http://www.ok-soft-gmbh.com/jqGrid/VS2008jQueryMVC.zip下载。 ASP.NET MVC 1.0中的代码应该是相同的,但是应该修补项目文件中的GUID和来自Web.config的一些字符串(请参阅http://www.asp.net/learn/whitepapers/aspnet-mvc2-升级说明 )。

这是因为global.asax中的注册路由不会识别此.svc文件。 它将尝试使用动作getmovies搜索该控制器并将失败。 尝试使用firebug进行调试。 您可以通过忽略global.asax中的此路由来解决此问题

我遇到了同样的问题。 我得出结论,路线干扰了服务电话。 你有没有尝试过Phil Haack的Route Debugger ? 它拯救了我的培根几次。

在结束时,我从其中一个控制器创建了一个端点。

奥列格,

你有你正在谈论的例子,因为我正在使用jqgrid / asp.net mvc和一个宁静的服务,并有一个时间的bugger。 这将有助于看到一个例子,因为我在墙上。 谢谢

SEM