代码之家  ›  专栏  ›  技术社区  ›  dcp

使用ASP.NET MVC的jquery-调用支持Ajax的Web服务

  •  2
  • dcp  · 技术社区  · 15 年前

    这是一个有点延续的 previous 问题。

    现在,我正试图调用一个支持Ajax的Web服务,我在ASP.NET MVC应用程序(即 MovieService.svc )但是我从来没有叫过这个服务 getMovies javascript函数。

    如果我在非ASP.NET MVC应用程序中尝试调用Ajax Web服务,那么调用Ajax Web服务的相同技术也可以正常工作,因此,我想知道在尝试调用Ajax Web服务时,ASP MVC路由是否以某种方式干扰了某些事情。

    你知道为什么我的网络服务没有被呼叫吗?下面的代码。

        <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" />
    

    这是我的注册路线代码:

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

    以下是我的电影服务类的样子:

    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();
            }
    
        }
    }
    
    4 回复  |  直到 15 年前
        1
  •  11
  •   Community CDub    8 年前

    您的主要问题是在 ajax 打电话。中的错误条目 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,并定义一些附加的 阿贾克斯 您喜欢的参数。 你不会在问题中发布 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() - doesn't serialize javascript Date objects? )为了减少一开始的问题,我定义 ReleaseDate 作为字符串。

    方法 IList<Movie> GetMovies() 像返回对象数组一样返回JSON数据 电影 . 所以jqgrid作为对HTTP的响应 GET 请求接收来自 MovieService.svc/GetMovies URL数据如下:

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

    我可以说,它不是典型的数据格式,正在等待jqgrid(与 http://www.trirand.com/jqgridwiki/doku.php?id=wiki:retrieving_data#json_data )为了能够将数据放入jqgrid中,我们必须定义 JSON阅读器 . 所以我们要跟踪

    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),服务器必须返回排序的数据。有关详细信息,请参阅的说明 prmNames 参数对 http://www.trirand.com/jqgridwiki/doku.php?id=wiki:options 和说明 sopt 参数对 http://www.trirand.com/jqgridwiki/doku.php?id=wiki:singe_searching .

    关于 数据类型:“json” 我们定义 dataType: 'json' 参数 阿贾克斯 (不要混淆 数据类型 参数)。中所有字段的名称 colModel 我们定义 准确的 与JSON对象中的字段名相同。一些附加参数 viewrecords , rownumbers , sortable headertitles 在这个例子中不是很重要,我选择那里是因为1)我喜欢那里,2)我设置了 rowNum: 0 使选项成为可能 rownumbers: true 工作正常,不显示以-5开头的负数,如果 rowNum: 5 就像你最初的例子一样。

    ajaxGridOptions: { contentType: "application/json" } 我们定义了其他参数, 直接的 转发给 阿贾克斯 .

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

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

    它定义所有行的ID都具有名称“ID”(请参见 class Movie repeatitems: false “假设我们希望通过字段名(定义于 共模 )而不是每个位置的默认定义。定义 root 有点奇怪,但它定义了如何找到 属于 JSON数据内部。JSON数据的默认格式如下

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

    行的根定义为 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 . 所以我们不能进行数据分页。你可以扩展 JSON阅读器 函数定义 , 全部的 记录 (也作为函数)像

    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。然后设置 罗纳姆:0 不再需要了。

    我这样展示只是为了展示jqgrid的灵活性。只有在访问无法更改的Web服务器时,才应使用描述的方法。jqgrid具有以下功能 分页 , 分选 和两种 搜索 (更多的是用相应选择中的位置过滤)数据:简单和高级。如果我们想要在我们的网页上的jqgrid内部有这些好的特性,我们应该在Web服务中定义一个额外的方法,比如

    [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<jqGridRow> rows { get; set; }
    }
    public class jqGridRow
    {
        public string id { get; set; }
        public List<string> cell { get; set; }
    }
    

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

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

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

    P.S.:关于jsonreader,您可以阅读更多内容 http://www.trirand.com/jqgridwiki/doku.php?id=wiki:检索数据json数据 . 一个我以前的答案 Mapping JSON data in JQGrid 对你来说也很有趣。

    更新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-upgrade-notes )

        2
  •  0
  •   Sundararajan S    15 年前

    这是因为global.asax中注册的路由将无法识别此.svc文件。它将尝试用action getmovies搜索该控制器,并将失败。尝试使用Firebug进行调试。 您可以通过在global.asax中忽略此路由来修复此问题。

        3
  •  0
  •   Chuck Conway    15 年前

    我也遇到了同样的问题。我得出结论,路线干扰了服务电话。你试过菲尔·哈克的吗 Route Debugger ?它救了我几次培根。

    在“结束”中,我在其中一个控制器上创建了一个终结点。

        4
  •  0
  •   user351978    15 年前

    奥列格

    当我使用jqgrid/asp.net mvc和一个RESTful服务时,您是否有过这样的例子,并且有过一段时间的错误。这将有助于我在墙上看到一个例子。谢谢

    扫描电镜