关于使用ASP.NET MVC的jQuery:使用ASP.NET MVC的jQuery-调用启用了Ajax的Web服务

jquery with ASP.NET MVC - calling ajax enabled web service

这是上一个问题的延续。

现在,我试图调用在ASP.NET MVC应用程序(即MovieService.svc)中定义的启用AJAX的Web服务。 但是,从未在我的getMovies javascript函数中调用该服务。

如果我在非ASP.NET MVC应用程序中尝试该调用AJAX Web服务的相同技术,则可以正常工作,因此它使我怀疑ASP MVC路由在尝试进行AJAX Web服务调用时是否会以某种方式干扰事物 。

您是否知道为什么没有调用我的Web服务? 下面的代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
    <script src="<%= ResolveClientUrl("~/scripts/jquery-1.4.2.min.js") %>" type="text/javascript">

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

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

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

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

        });

   

   
        <%= Html.Encode(ViewData["Message"]) %>
    <p>

        To learn more about ASP.NET MVC visit
            http://asp.net/mvc.
   
</p>
    <table id="editgrid">
    </table>
   
   
    <input type="button" id="bedata" value="Edit Selected" />

这是我的RegisterRoutes代码:

1
2
3
4
5
6
7
8
9
10
11
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类的样子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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();
        }

    }
}


您的主要问题是在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的存在,您在< x6>读取从Web服务器返回的数据。

更新:
在我看来,稍后将描述编辑功能,并在此处说明如何获取JSON数据并将其填充到jqGrid中。

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

1
2
3
4
5
6
7
8
9
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; }
}

您应注意,Microsoft序列化DataTime类型不是可读的日期字符串,而是字符串/Date(utcDate)/,其中utcDate是此数字
(请参阅jQuery.param()-不序列化javascript Date对象吗?)。为了在开始时减少问题,我将ReleaseDate定义为字符串。

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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:prmNames参数的描述和http://www.trirand.com/上sopt参数的描述jqgridwiki / doku.php?id = wiki:singe_searching。

关于datatype: 'json',我们定义jQuery.ajaxdatatype: 'json'参数(不要混淆datatype参数内部的大小写)。 colModel中所有字段的名称与JSON对象中定义的字段名称完全相同。在此示例中,一些其他参数viewrecordsrownumberssortableheadertitles并不是很重要,我之所以选择了该位置,是因为1)我喜欢那里,以及2)设置rowNum: 0以使选项可以正常工作,并且如您的原始示例一样,如果rowNum: 5,则不会显示以-5开头的负行号。

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

此示例最复杂的部分是

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

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

1
2
3
4
5
6
7
8
9
10
{
  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)。您可以验证此奇怪的方法是否有效。典型的附加参数pagetotal(lastpage)和records在我们的JSON数据中不存在,它们将按照page:0, total:1, records:0进行初始化。因此,我们无法进行数据分页。您可以使用定义pagetotalrecords的函数(也可以作为函数)扩展jsonReader,例如

1
2
3
4
5
6
7
8
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具有分页,排序和两种数据搜索(更多的是在相应的SELECT中使用WHERE进行过滤)的功能:简单和高级。如果我们希望在网页上的jqGrid内具有这些不错的功能,则应在Web Service中定义其他方法,例如

1
2
3
4
5
6
7
8
9
10
[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

1
2
3
4
5
6
7
8
9
10
11
12
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; }
}

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

1
2
3
4
5
6
7
// 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上了解有关这种数据传输的更多信息。)

附注:关于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的参数以及将web.config的一部分描述为WCF服务接口的部分。

更新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- 升级说明)。

好。


奥列格

当我正在使用jqgrid / asp.net mvc和宁静的服务并有一段时间的bug时,您是否有您正在谈论的示例。 就像我在墙上一样,看到一个例子会有所帮助。 谢谢

扫描电镜


我遇到了同样的问题。 我得出的结论是,路由干扰了服务呼叫。 您是否尝试过Phil Haack的Route Debugger? 它节省了我的培根几次。

最后,我在其中一个控制器上创建了一个端点。


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