2 Stimmen

jquery mit ASP.NET MVC - Aufruf eines Ajax-fähigen Webdienstes

Dies ist eine Art Fortsetzung eines vorherige Frage.

Jetzt versuche ich, einen AJAX-fähigen Webdienst aufzurufen, den ich innerhalb der ASP.NET MVC-Anwendung definiert habe (d. h. die MovieService.svc ). Aber der Dienst wird in meinem System nie aufgerufen. getMovies javascript-Funktion.

Diese gleiche Technik des Aufrufs der AJAX-Webdienst funktioniert ok, wenn ich es in einer nicht ASP.NET MVC-Anwendung versuchen, so dass es mich fragen, ob vielleicht die ASP MVC-Routen mit Dingen irgendwie stören, wenn es versucht, den AJAX-Webdienst-Aufruf zu machen.

Haben Sie eine Idee, warum mein Webdienst nicht aufgerufen wird? Code unten.

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

Hier ist mein RegisterRoutes-Code:

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

So sieht meine MovieService-Klasse aus:

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

    }
}

11voto

Oleg Punkte 219333

Ihr Hauptproblem ist, dass Sie nicht absolute URLs in der ajax anrufen. Falsche Einträge in web.config kann auch Probleme machen. Außerdem verwenden Sie datatype: getMovies anstelle von datatype: 'json' y postData: yourData . Der Weg mit datatype als Funktionen existieren (siehe http://www.trirand.com/jqgridwiki/doku.php?id=wiki:retrieving_data#function ), aber seit jqGrid 3.6.5 haben Sie einen direkteren Weg innerhalb von jsonReader um die vom Webserver zurückgegebenen Daten zu lesen.

AKTUALISIERT: Es scheint mir, dass die Beschreibung der Bearbeitungsfunktionen werde ich später machen und erklären hier nur, wie man JSON-Daten zu erhalten und füllen es innerhalb von jqGrid.

Zunächst einmal kann jqGrid selbst die JSON-Daten vom Server anfordern. Wir brauchen also keine separate jQuery.ajax anrufen. Sie müssen lediglich eine URL definieren, die auf den Server verweist, und einige zusätzliche jQuery.ajax Parameter, die Sie bevorzugen. Sie geben in Ihrer Frage nicht die Definition der Movie Klasse. Ich definiere sie also selbst wie folgt

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

Sie sollten bemerken, dass Microsoft serialisieren DataTime nicht als lesbare Datumszeichenfolge, sondern als String /Date(utcDate)/ , wobei utcDate ist diese Zahl (siehe jQuery.param() - nicht serialisieren javascript Datum Objekte? ). Um am Anfang weniger Probleme zu haben, definiere ich ReleaseDate als Zeichenkette.

Methode IList<Movie> GetMovies() gibt JSON-Daten wie ein Array von Objekten zurück Movie . Also jqGrid als Antwort auf HTTP GET Anfrage erhalten von der MovieService.svc/GetMovies URL die Daten wie folgt:

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

Ich kann sagen, dass es nicht typisch Format von Daten, die warten jqGrid (vergleichen Sie mit http://www.trirand.com/jqgridwiki/doku.php?id=wiki:retrieving_data#json_data ). Um die Daten innerhalb von jqGrid platzieren zu können, müssen wir eine jsonReader . Wir tun also Folgendes

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

HINWEIS : Ich habe aus dem Beispiel alle Sortierparameter entfernt, da im Falle einer Anfrage von JSON-Daten der Sortierparameter nur an den Server gesendet wird (einige zusätzliche Parameter fügen der Server-URL hinzu) und der Server die sortierten Daten zurückgeben muss. Für weitere Informationen siehe Beschreibung von prmNames Parameter auf http://www.trirand.com/jqgridwiki/doku.php?id=wiki:options und Beschreibung von sopt Parameter auf http://www.trirand.com/jqgridwiki/doku.php?id=wiki:singe_searching .

In Bezug auf datatype: 'json' definieren wir dataType: 'json' Parameter von jQuery.ajax (nicht zu verwechseln mit dem Fall innerhalb von datatype Parameter). Die Namen aller Felder innerhalb von colModel definieren wir genau mit den Feldnamen in unseren JSON-Objekten übereinstimmen. Einige zusätzliche Parameter viewrecords , rownumbers , sortable y headertitles sind in diesem Beispiel nicht sehr wichtig, ich habe sie gewählt, weil 1) ich sie mag und 2) ich die rowNum: 0 um die Optionen zu ermöglichen rownumbers: true korrekt funktioniert und uns keine negativen Zeilennummern, die mit -5 beginnen, anzeigt, wenn rowNum: 5 wie in Ihrem ursprünglichen Beispiel.

Mit ajaxGridOptions: { contentType: "application/json" } definieren wir zusätzliche Parameter, die direkt weitergeleitet an den jQuery.ajax .

Der komplexeste Teil dieses Beispiels ist

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

Sie definiert, dass die Id aller Zeilen den Namen "Id" hat (siehe Definition der class Movie ). " repeatitems: false ", dass jedes Datenfeld, das wir mit dem Feldnamen identifizieren wollen (definiert in colModel ) anstelle der Standarddefinition pro Position. Die Definition von root ist ein wenig seltsam, aber es definiert, wie man die Wurzel de Zeilen innerhalb von JSON-Daten. Das Standardformat der JSON-Daten ist das folgende

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

und die Wurzel der Zeilen sind definiert als root: "rows" . Wenn also die JSON-Daten, die der Variablen res kann die Wurzel zurückgegeben werden als res.rows . Um jqGrid zu ermöglichen, unsere Daten zu lesen, definieren wir jsonReader.root als Funktion (dieses Feature existiert seit jqGrid 3.6.5, siehe http://www.trirand.com/jqgridwiki/doku.php?id=wiki:change#additions_and_changes ). Sie können sich davon überzeugen, dass diese seltsame Methode funktioniert. Die typischen zusätzlichen Parameter page , total ( lastpage ) und records sind in unseren JSON-Daten nicht vorhanden und werden wie folgt initialisiert page:0, total:1, records:0 . Wir sind also nicht in der Lage, Daten auszulagern. Sie können erweitern jsonReader mit Funktionen, die page , total y records (auch als Funktionen) wie

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

was unseren jsonReader vervollständigen wird. Dann Einstellung von rowNum: 0 wird nicht mehr benötigt.

Ich habe diesen Weg nur gezeigt, um die Flexibilität von jqGrid zu zeigen. Sie sollten die beschriebene Methode nur verwenden, wenn Sie auf einen Webserver zugreifen, den Sie nicht ändern können. jqGrid hat Funktionen wie ausrufen , Sortierung und zwei Arten von Suche (mehr als Filterung mit WHERE im entsprechenden SELECT) von Daten: einfach und fortgeschritten. Wenn wir diese netten Features innerhalb von jqGrid auf unseren Webseiten haben wollen, sollten wir im Web Service eine zusätzliche Methode definieren wie

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

Oder wenn wir die kompakteste Form der Datenübertragung vom Server zum Client verwenden wollen, dann

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

(Weitere Informationen über diese Art der Datenübertragung finden Sie unter http://www.trirand.com/blog/jqgrid/jqgrid.html wenn Sie im linken Baumteil "Data Mapping" und dann "Data Optimization" wählen)

P.S.: Über jsonReader können Sie mehr lesen auf http://www.trirand.com/jqgridwiki/doku.php?id=wiki:retrieving_data#json_data . Ein meine alte Antwort Abbildung von JSON-Daten in JQGrid kann auch für Sie interessant sein.

AKTUALISIERT 2 : Da Sie die Antwort nicht als akzeptiert markieren, bleiben einige Probleme bestehen. Also habe ich ein neues Projekt in Visual Studio 2010 erstellt, das zeigt, was ich geschrieben habe. Sie können den Quellcode herunterladen von http://www.ok-soft-gmbh.com/jqGrid/jQueryMVC.zip . Vergleichen Sie mit Ihrem Projekt, insbesondere den Teil mit der vollständigen URL als Parameter von jqGrid und einen Teil der web.config, der die WCF-Service-Schnittstelle beschreibt.

AKTUALISIERT 3 : Ich benutze VS2010 nicht so lange Zeit. So konnte ich sehr schnell ein Downgrade auf VS2008 durchführen. Also fast den gleichen Code arbeiten in Visual Studio 2008, aber mit ASP.NET MVC 2.0 können Sie von herunterladen http://www.ok-soft-gmbh.com/jqGrid/VS2008jQueryMVC.zip . Der Code in ASP.NET MVC 1.0 sollte derselbe sein, aber eine GUID aus der Projektdatei und einige Strings aus Web.config sollten geändert werden (siehe http://www.asp.net/learn/whitepapers/aspnet-mvc2-upgrade-notes ).

0voto

Sundararajan S Punkte 1308

Das liegt daran, dass die registrierte Route in der global.asax diese .svc-Datei nicht erkennt. Sie versucht, nach dem Controller mit der Aktion getmovies zu suchen und schlägt fehl. Sie können dies beheben, indem Sie diese Route in der global.asax ignorieren.

0voto

Chuck Conway Punkte 16031

Ich bin auf das gleiche Problem gestoßen. Ich kam zu dem Schluss, dass die Routen den Dienstabruf behinderten. Haben Sie es mit Phil Haack's Routen-Debugger ? Das hat mir schon ein paar Mal den Hintern gerettet.

Am Ende habe ich einen Endpunkt an einem der Controller erstellt.

0voto

user351978 Punkte 1

Oleg,

Haben Sie das Beispiel, das Sie sprachen, wie ich mit jqgrid/asp.net mvc und ein restful Service arbeiten und mit einem bugger einer Zeit. Es würde helfen, ein Beispiel zu sehen, wie ich an einer Wand bin. Thx

SEM

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X