views:

218

answers:

4

The following code populates a second dropdown when the first dropdown changes (i.e. cascading dropdowns). However, the Ajax call isn't firing, and I can't figure out why. I'm not getting any syntax or runtime errors. When in debug mode, the GetPlans action is never being called. The inner alert is never called, but the outer one is. To make matters worse, this same setup is working elsewhere in my app! Here's all the pertinent pieces (let me know if I've left out some important details):

"Report/Auth" View:

<script type="text/javascript" src="../../Scripts/jquery-1.3.2.min.js"></script>

<script type="text/javascript" src="../../Scripts/MicrosoftAjax.js"></script>

<script type="text/javascript">

    $(function() {
        $("#year").change(function() {

            var year = $("#year > option:selected").attr("value");
            var rid = $("#rid").attr("value");

            $.ajax({
                type: "GET",
                contentType: "application/json; charset=utf-8",
                url: "GetPlans/" + rid + "/" + year,
                data: "{}",
                dataType: "json",
                success: function(data) {
                    alert('inside');
                    if (data.length > 0) {
                        var options = '';
                        for (p in data) {
                            var plan = data[p];
                            options += "<option>" + plan + "</option>";
                        }
                        $("#plan").html(options);

                    } else {
                        $("#plan").html('');
                    }
                }
            });

            alert("outer");
        });
    });

</script>

<% Using Html.BeginForm()%>
<%=Html.Hidden("rid")%>
Year:
<%=Html.DropDownList("year", Model.Years)%>
Plan:
<%=Html.DropDownList("plan")%>
<% End Using%>

ReportController:

Function Auth(ByVal rid As Integer) As ActionResult

    ViewData("plan") = New SelectList(New List(Of SelectListItem))
    Return View(New Auth)

End Function

Public Function GetPlansByYear(ByVal rid As Integer, ByVal year As Integer) As JsonResult

    Dim plans = _
        (From bp In BenefitDataContext.GetContext.BenefitPlans _
         Where bp.Benefit.repository_id = rid _
         And bp.Benefit.plan_year_val = year _
         Select bp.MphcPlan).Distinct

    Return New JsonResult _
        With {.Data = _
                From p In plans _
                Select New SelectListItem _
                    With {.Text = p.plan_code & " - " & p.plan_desc, _
                          .Value = p.plan_id}}

End Function

Auth class:

Public Class Auth

    Private _years As SelectList
    Public Property Years() As SelectList
        Get
            Return _years
        End Get
        Set(ByVal value As SelectList)
            _years = value
        End Set
    End Property

    Public Sub New()

        Dim disinctYears = _
            (From b In BenefitDataContext.GetContext.Benefits _
             Where b.repository_id = 1 _
             Select b.plan_year_val).Distinct

        Dim yearList = _
            From y In disinctYears _
            Order By y _
            Select New SelectListItem _
                With {.Text = y, _
                      .Value = y, _
                      .Selected = (y = Now.Year)}

        Years = New SelectList(yearList, "Value", "Text")

End Sub

Global.asax - Register Routes:

routes.MapRoute( _
    "AuthReportGetPlans", _
    "GetPlans/{rid}/{year}", _
    New With {.controller = "Report", .action = "GetPlansByYear", .rid = "", .year = ""} _
)

Any ideas on how to figure out what's going on?

UPDATE: Found the problem via inspecting the error output of the Ajax call, so now I know the cause of the problem: the URL is being appended to the current path instead of being called from the route, i.e. /Reports/Auth/GetPlans/1/2009 instead of /GetPlans/1/2009. This is confusing since it appears that it's set up correctly in global.asax to map to route I set up, and as stated previously I have this set up in another view and it's working fine there. Any input as to why the Ajax call is specifying the wrong path?

+2  A: 

Try capturing the error event of the .ajax call and see if it tells you any extra info

$.ajax({
    type: "GET",
    contentType: "application/json; charset=utf-8",
    url: "GetPlans/" + rid + "/" + year,
    data: "{}",
    dataType: "json",
    success: function(data) {
        alert('inside');
        if (data.length > 0) {
            var options = '';
            for (p in data) {
                var plan = data[p];
                options += "<option>" + plan + "</option>";
            }
            $("#plan").html(options);
        } else {
            $("#plan").html('');
        }
    },
    error: function(xhr){
        alert('something is b0rked')
        // take a look at xhr.status and xhr.responseText
    }
});
Corey Downie
That's exactly what I was missing. The call was bombing but not telling me why. Now I know that it's appending the URL to the current path (original question updated with details). Thanks a bunch - this will come in handy down the road.
gfrizzle
+1  A: 

Is it not hitting the URL at all? Maybe you should make your URL absolute:

url: "/GetPlans/" + rid + "/" + year

Also try binding the action on $(document).ready() instead of immediately.

Mike Robinson
Interesting. Making it absolute (i.e. adding the leading slash) seemed to fix the problem. It's interesting because my other implementation of this code didn't have the leading slash and worked fine (that one also works fine WITH the leading slash, so I left it in both places).
gfrizzle
The leading slash makes your URL absolute. I'll bet you were in a subdirectory when the code stopped.
Mike Robinson
A: 

Check to make sure that MicrosoftAjax.js isn't using the $ for it's own purposes.

If it is, you can find information on how to use something other than the $ on this page

For example:

var $jQuery = jQuery.noConflict();


$jQuery(function() {
    $jQuery("#year").change(function() {

        var year = $jQuery("#year > option:selected").attr("value");
        var rid = $jQuery("#rid").attr("value");

        $jQuery.ajax({ ...

...

Mark Worth
A: 

Silly question... Are you sure your script paths are correct? I had to do some hacking around to ensure I was in the right location (see this thread)

I'm not a huge jQuery user (I know very little and am therefore dangerous), I'd be tempted to make sure by sticking

alert('Yep, I'm running');

somewhere in your function.

EDIT

The thread I pointed to doesn't specifically address the path issue. Basicvally I have a helper method called GetRootPath that returns the root of the site, and I call the jQuery files as follows

<script src="<%= Html.GetBasePath() %>Scripts/jQuery.js" type="text/javascript"></script>

Sorry for the confusion

And now, I shall attempt to teach my grandmother to suck eggs. ;)

ZombieSheep