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

dcp*_*dcp 2 ajax asp.net-mvc jquery jqgrid

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

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

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

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

    <script src="<%= ResolveClientUrl("~/scripts/jquery-1.4.2.min.js") %>" type="text/javascript"></script>

    <script src="<%= ResolveClientUrl("~/scripts/grid.locale-en.js") %>" type="text/javascript"></script>

    <script src="<%= ResolveClientUrl("~/scripts/jquery-ui-1.8.1.custom.min.js") %>"
        type="text/javascript"></script>

    <script src="<%= ResolveClientUrl("~/scripts/jquery.jqGrid.min.js") %>" type="text/javascript"></script>

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

        });

    </script>

    <h2>
        <%= Html.Encode(ViewData["Message"]) %></h2>
    <p>
        To learn more about ASP.NET MVC visit <a href="http://asp.net/mvc" title="ASP.NET MVC Website">
            http://asp.net/mvc</a>.
    </p>
    <table id="editgrid">
    </table>
    <div id="pager" style="text-align: center;">
    </div>
    <input type="button" id="bedata" value="Edit Selected" />
Run Code Online (Sandbox Code Playgroud)

这是我的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
    );
}
Run Code Online (Sandbox Code Playgroud)

这是我的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<Movie> GetMovies()
        {
            return Persistence.GetMovies();
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

Ole*_*leg 11

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

更新: 在我看来,我将在稍后介绍编辑功能,并在此解释如何获取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; }
}
Run Code Online (Sandbox Code Playgroud)

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

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

 [{"Id":1, "Name": "E.T.", "Director": "Steven Spielberg",...},{...},...]
Run Code Online (Sandbox Code Playgroud)

我可以说这不是典型的数据格式,它正在等待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 });
Run Code Online (Sandbox Code Playgroud)

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

关于datatype: 'json' 我们定义dataType: 'json'参数jQuery.ajax(不要混淆datatype参数内的情况).colModel我们内部所有字段的名称与 JSON对象中的字段名称完全相同.一些额外的参数viewrecords,rownumbers,sortableheadertitles在这个例子中不是很重要,我选用那里,因为1)我喜欢那里,2)我将rowNum: 0做出可能的选项rownumbers: true工作正确的,而不是给我们的负面行号开始-5如果rowNum: 5像你原始的例子.

随着ajaxGridOptions: { contentType: "application/json" } 我们定义将被附加参数直接转发到jQuery.ajax.

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

jsonReader: { repeatitems: false, id: "Id", root: function(obj) { return obj; }}
Run Code Online (Sandbox Code Playgroud)

它定义了所有行的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"]},
      ...
  ]
}
Run Code Online (Sandbox Code Playgroud)

并且行的根定义为root: "rows".因此,如果分配给变量的JSON数据res,则可以将根返回为res.rows.为了允许jqGrid读取我们的数据,我们将其定义jsonReader.root为一个函数(此功能自jqGrid 3.6.5起见,请参阅http://www.trirand.com/jqgridwiki/doku.php?id=wiki:change#additions_and_changes).您可以验证这种奇怪的方法是否有效.典型的附加参数page,total(lastpage),并records没有我们的JSON数据的内部存在,他们将被初始化为以下page:0, total:1, records:0.所以我们无法进行数据分页.您还可以扩大jsonReader与功能定义page,totalrecords(也可作为功能),如

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; }
}
Run Code Online (Sandbox Code Playgroud)

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

我这样展示只是为了展示jqGrid的灵活性.仅当您访问无法更改的Web服务器时,才应使用所述方法.jqGrid具有分页,排序和两种搜索(更像是在相应的SELECT中使用WHERE过滤)数据的功能:简单和高级.如果我们想在我们的网页上的jqGrid中有这些不错的功能,我们应该在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)
Run Code Online (Sandbox Code Playgroud)

哪里 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<jqGridRow> rows { get; set; }
}
public class jqGridRow
{
    public string id { get; set; }
    public List<string> cell { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

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

// 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<List<string>> rows { get; set; }// first element in every row must be id of row.
}
Run Code Online (Sandbox Code Playgroud)

(如果您在左侧树部分"数据映射"中选择,然后选择"数据优化",您可以在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-升级笔记).