0

In my ASP.NET MVC app, I've got this AJAX call in my View's script section:

$(".ckbx").change(function () {
. . .
    $.ajax({
        type: 'GET',
        url: '@Url.Action("GetUnitReportPairVals", "Home")',
        data: { unit: unitval, report: rptval },
        cache: false,
        success: function (result) {
            alert(result);
        }
    });
});

Stepping through the Controller action being called:

public ActionResult GetUnitReportPairVals(string unit, string report)
{
    HomeModel model = new HomeModel();

    int rptId = GetReportIDForName(report);

    DataTable UnitReportPairEmailValsDT = new DataTable();
    UnitReportPairEmailValsDT = SQL.ExecuteSQLReturnDataTable(
        SQL.UnitReportPairEmailQuery, 
        CommandType.Text, 
        new SqlParameter()
                {
                    ParameterName = "@Unit",
                    SqlDbType = SqlDbType.VarChar,
                    Value = unit
                },
                new SqlParameter()
                {
                    ParameterName = "@RptID",
                    SqlDbType = SqlDbType.Int,
                    Value = rptId
                }
                );

    model.UnitReportPairEmailVals = UnitReportPairEmailValsDT;
    return View(model);
}

...it all seems to be working fine; "model" contains the expected value in UnitReportPairEmailVals.

But I never see the alert message from here in the Ajax call:

success: function (result) {
    alert(result);
} 

So why is the "success" function of the jQuery AJAX call not being reached?

UPDATE

BTW, this may be a clue: the final line of my Controller method:

return View(model);

...paints the word "View" red as a Rhode Island rooster's comb. But if it's not supposed to be that, what is it supposed to be? That's the exact same thing I have at the end of my "public ActionResult Index()" controller Action, which works fine.

UPDATE 2

I changed the end of my Ajax call to:

success: function (result) {
    alert(result);
},
failure: function (error) {
    alert(error);
}

...and the end of my Controller method to:

return Json(new { Result = model }, JsonRequestBehavior.AllowGet);

...but I get no alert, neither from success nor from failure.

UPDATE 3

Note: When I tried this:

var model = JSON.stringify({ unit: unitval, report: rptval });
    $.ajax({
        type: 'GET',
        url: '@Url.Action("GetUnitReportPairVals", "Home")',
        data: model,
        contentType: 'application/json',
        cache: false,
        success: function (result) {
            alert(result);
        },
        error: function (result) {
            debugger;
        }
    });

..."unit" was null, and so it wouldn't fly at all.

When I changed it to this (removed line 1 and changed the "data" arg back to what I had been using previously):

$.ajax({
    type: 'GET',
    url: '@Url.Action("GetUnitReportPairVals", "Home")',
    data: { unit: unitval, report: rptval }, 
    contentType: 'application/json',
    cache: false,
    success: function (result) {
        alert(result);
    },
    error: function (result) {
        alert('failed');
    }
});

..."unit" is what I expect it to be (and "report", too), but I ultimately see 'failed'.

UPDATE 4

Once I pieced together several different answers to this and related questions, I wrote up a tip on how to do this here.

UPDATE 5

I've got this [working] ajax call [working]:

var model = JSON.stringify({ unit: unitval, report: 1 });
$.ajax({
    type: 'GET',
    url: '@Url.Action("GetUnitDataRangeParamsVals", "UnitReportDataRangeParams")',
    data: { unit: unitval, report: 1 },
    contentType: 'application/json',
    cache: false,
    success: function (returneddata) {
        populatedatarangeprams(1, returneddata);
    },
    error: function () {
        alert('error - returneddata.error.stringify');
    }
});

...but I'm not using the "model" that's declared and, according to my understanding, it is paired with "contentType: 'application/json',"

So I thought what I should do is something like this instead:

var model = JSON.stringify({ unit: unitval, report: 1 });
$.ajax({
    type: 'GET',
    url: '@Url.Action("GetUnitDataRangeParamsVals", "UnitReportDataRangeParams")',
    data: model,
    contentType: 'application/json',
    cache: false,
    success: function (returneddata) {
        populatedatarangeprams(1, returneddata);
    },
    error: function () {
        alert('error - returneddata.error.stringify');
    }
});

Now the data passed to the controller's method is in json stringified format (encapsulated in "model").

But, it doesn't even work.

It works with the first block, but not the second.

So I removed both the "model" and the "contentType" lines, and changed the "data" line back to what it had been, and it works fine. So are they useless, or am I employing them wrongly?

B. Clay Shannon-B. Crow Raven
  • 8,547
  • 144
  • 472
  • 862
  • 1
    Are you able to add a breakpoint to the controller method and hit that breakpoint when you submit? As a side note, I normally use the following in my ajax: contentType: 'application/json', data: JSON.stringify(model) – nurdyguy Apr 21 '16 at 21:11
  • Yes, I can step through it fine; where do you put the jazz you mentioned above? – B. Clay Shannon-B. Crow Raven Apr 21 '16 at 21:14
  • 1
    Oh, yeah you need to change the response type of the controller method. ActionResult means the controller is going to try to find a view and do that whole thing. But if you are just using ajax then you want to use JsonResult instead as the return type. Then a json string will be returned back to the ajax. I'll write it up as an answer in just a sec. – nurdyguy Apr 21 '16 at 21:17
  • To what? I'm using the same response type (ActionResult) in the Index method, and it works dandy... – B. Clay Shannon-B. Crow Raven Apr 21 '16 at 21:19
  • do you have created View for the action? – Ehsan Sajjad Apr 21 '16 at 21:30
  • Add error: function(result) { debugger; } after the success in the ajax. (see my answer below). This will allow you to step through and see the error response which will have the actual stack trace for the error. It probably says something about not being able to find the view (as a couple have mentioned). – nurdyguy Apr 21 '16 at 21:36

2 Answers2

1

Here are a few snippets I use when doing ajax in ASP.NET MVC.

$(".ckbx").change(function () {
    .....
    var model = JSON.stringify({ unit: unitval, report: rptval });
    $.ajax({
        type: 'GET',
        url: '@Url.Action("GetUnitReportPairVals", "Home")',
        data: model,
        contentType: 'application/json',
        cache: false,
        success: function (result) {
            alert(result);
        },
        error: function(result) {
            debugger;
        }
    });
});

Sometimes those two changes (as compared to your original) are not necessary but ASP.NET can be slightly picky if the json isn't just right and this helps with that. Since you are able to step into the controller method, this wasn't your problem, but it can be handy.

Your real problem was the return type on the controller method. ActionResult means it is going to look for a corresponding view and build out the html based on that view. But if you are doing ajax then you probably don't want that.

public JsonResult GetUnitReportPairVals(string unit, string report)
{
    // do some stuff
    // then create response model
    var model = ...//whatever data you are returning here
    return Json(model);
}

This is the "standard" approach for ajax calls in ASP.NET MVC.

As you noted in your comment, ActionResult works great in the Index method. Yes, because the purpose of the index method is to load a page. Generally, if the method is used to load a page then you'll use ActionResult because it will use a view to create the html for that page. But if you are just submitting info and then returning a response like "success" then you don't want a whole html response, you want json. That's why JsonResult works here.

nurdyguy
  • 2,876
  • 3
  • 25
  • 32
1

I suspect you do not have created the view for this action and that would cause ajax call to fail in case of exception as razor engine will not be able to find the View. Make sure View exists for this action or if you want to return some other view specify that like:

 return View(model,"ViewName");

you can also add failure call back to see what is going wrong:

success: function (result) {
            alert(result);
        },
error: function(error){
           console.log(error);
        }

Update:

If you only want to return data then use Json:

return Json(new {Result = model },JsonRequestBehavior.AllowGet);
Ehsan Sajjad
  • 61,834
  • 16
  • 105
  • 160