1

I'm struggling a little bit with outputting controller data in C# MVC, to JSONP, for use with JQuery autocomplete. All i want to do, is take 2 parameters, and a callback for JSONP to work, and the query return the matching course titles available, based on the search.

CourseController.cs

    public JsonResult GetPredictiveCourseTitleSearchResults()
    {
        var jsonbuilder = "";
        var q = HttpContext.Request.Params["q"];
        var year = HttpContext.Request.Params["year"];
        var callback = HttpContext.Request.Params["callback"];
        var model = new courseModel
        {
            SearchList = GetCourses(q,year)
        };
        var results = model.SearchList.Items.ToList();
        int count = results.Count();
        int resultCount = 0;

        if (callback != "")
        {
            jsonbuilder += callback + "(";
        }
        jsonbuilder += "[";
        foreach(var result in results)
        {

            if(resultCount+1 == count)
            {
                jsonbuilder += "{\"title\":" + "\"" + result.Fields["title"].ToString() + "\"}";
            }
            else
            {
                jsonbuilder += "{\"title\":" + "\"" + result.Fields["title"].ToString() + "\"},";
            }

            resultCount++;
        }
        jsonbuilder += "]";
        if (callback != "")
        {
            jsonbuilder += ")";
        }
        return Json(jsonbuilder, JsonRequestBehavior.AllowGet);
    }

CourseModel.cs

public class courseModel
{
    public ListModel<Item> SearchList { get; set; }
    public string title { get; set; }

}

App.js

 $("#course_search_input")
     .bind("keydown", function (event) {
         if (event.keyCode === $.ui.keyCode.TAB &&
             $(this).autocomplete("instance").menu.active) {
             event.preventDefault();
         }
     })
    .autocomplete({
        source: function( request, response ) {
            $.ajax({
                url: "http://leedsbeckett/search/getpredictivecoursetitlesearchresults/",
                dataType: "jsonp",
                type: "POST",
                data: {
                    q: request.q,
                    year: $("#selectedyear").val()
                },
                success: function (data) {
                    response( $.map( data.stuff, function ( item ) {
                        return {
                            label: item.title,
                            value: item.title
                        };
                    }));
                },
                error: function (XHR, textStatus, errorThrown, data) {

                    alert("Data"+data);
                    alert("XHR error: " + XHR);
                    alert("error: " + textStatus);
                    alert("error: " + errorThrown);
                }
            });
        },
        minLength: 3,
        select: function( event, ui ) {
            log( ui.item ?
              "Selected: " + ui.item.label :
              "Nothing selected, input was " + this.value);
        },
        open: function() {
            $( this ).removeClass( "ui-corner-all" ).addClass( "ui-corner-top" );
        },
        close: function() {
            $( this ).removeClass( "ui-corner-top" ).addClass( "ui-corner-all" );
        }

Output of JSON file

"jQuery1111023084966000169516_1457628798511([{\"title\":\"Course title example\"}])"

This however isn't loaded, it just errors in the JQuery, with data unknown.

I've also tried:

JavaScriptSerializer js = new JavaScriptSerializer();
        CourseJSON [] courses = js.Deserialize<CourseJSON[]>(jsonbuilder);
return Json(courses, JsonRequestBehavior.AllowGet);

But this gave an error due to it not recognising the callback prefix.

Any help would be much appreciated, as i'm not sure where i'm going wrong!

Thanks,

Andy

Andyram2k
  • 33
  • 1
  • 6

2 Answers2

0

You have to set the proper content type. It should be application/Javascript in the $.ajax call.

Best content type to serve JSONP?

or

url: "http://leedsbeckett/search/getpredictivecoursetitlesearchresults/",
            dataType: "jsonp",
            type: "POST", **jsonp:"callback"**,
Community
  • 1
  • 1
Thanigainathan
  • 1,505
  • 14
  • 25
  • thanks for the answer. I've tried this, and i still get an error of err:r "parsererror" Also, "Jquery 9083450845098345_509348598340598 was not called" This might be a C# thing instead of the JQuery side? Any help appreciated! Andy – Andyram2k Mar 13 '16 at 23:09
  • I have updated the answer above. – Thanigainathan Mar 14 '16 at 00:17
  • Hi, thanks for amending your answer. I'm still getting a parseerror after trying both of the suggestions above. – Andyram2k Mar 14 '16 at 09:39
0

I've found the issue as to why the JSONP wasn't returning properly from C#

Where i had jsonresult returning json, it needed to be actionresult, returning contenttype, as found after much searching here: Can I convert a JSON string into JsonResult?

Adding a contenttype then turns the string into true JSON, which the JS can read:

public ActionResult GetPredictiveCourseTitleSearchResults()
    {
        var jsonbuilder = "";
        var q = HttpContext.Request.Params["q"];
        var year = HttpContext.Request.Params["year"];
        var callback = HttpContext.Request.Params["callback"];
        var model = new courseModel
        {
            SearchList = GetCourses(q,year)
        };
        var results = model.SearchList.Items.ToList();
        int count = results.Count();
        int resultCount = 0;

        if (callback != "")
        {
            jsonbuilder += callback + "(";
        }
        jsonbuilder += "[";
        foreach(var result in results)
        {

            if(resultCount+1 == count)
            {
                jsonbuilder += "{\"title\":\"" + result.Fields["title"].ToString() + "\"}";
            }
            else
            {
                jsonbuilder += "{\"title\":\"" + result.Fields["title"].ToString() + "\"},";
            }

            resultCount++;
        }
        jsonbuilder += "]";
        if (callback != "")
        {
            jsonbuilder += ")";
        }
        return new ContentResult { Content = jsonbuilder, ContentType = "application/json" };
        //return Json(jsonbuilder, JsonRequestBehavior.AllowGet);
    }

Thanks for your help in diagnosing the issue Thanigainathan.

Community
  • 1
  • 1
Andyram2k
  • 33
  • 1
  • 6