12

This is an MVC3 app. I have the following javascript call to my action:

 function editDescription(docId,fileName, fileDescription) {
    $.ajax({
         type: "POST",
         url: "/OrderDetail/LoadModelData",
         contentType: "application/json; charset=utf-8",
         data: "{'id': '"+docId +"', 'filename': '"+fileName+"', 'description': '"+fileDescription+"'}",
         dataType: "json",
         success: function (result) {
         alert("ok: "+ result.d);
         },
         error: function (result) {
             alert('Oh no: '+ result.responseText);
         }
     });

Heres my action:

    [HttpPost]
    public string LoadModelData(string id, string filename, string description)
    {
        return filename;
    }

I run the code, the action gets called with the parameters, nothing is null, but the error function gets called every time. So the alert box with 'Oh no' in it appears every time, but the string being returned from the action is correct. If the filename is test.pdf the error alert box says

    'Oh No: test.pdf'. 

I looked in Firebug and there are no errors. Why isn't the success function being called despite the fact there are no errors?

Cœur
  • 37,241
  • 25
  • 195
  • 267
BoundForGlory
  • 4,114
  • 15
  • 54
  • 81
  • The filename. Thats doing what its supposed to. The error function keeps getting called and sooner or later an actual error will occur – BoundForGlory Jun 13 '12 at 16:34

2 Answers2

16

You are expecting (returning) a string value from your action method. Why do you need to specify the datatype as json then ? Remove that and see what happens. And there is no d property from the response ! so just use result in the alert.

$.ajax({
         type: "POST",
         url: "/OrderDetail/LoadModelData",
         contentType:"application/json; charset=utf-8",         
         data: JSON.stringify({ 
                             id: docId, 
                             filename: fileName, 
                             description: fileDescription 
                            }),
         success: function (result) {
         alert("ok: "+ result);
         },
         error: function (result) {
             alert('Oh no: '+ result.responseText);
         }
     });

the datatype property tells the server that what kind of content the client is expecting back as the result.

EDIT : As Darin mentioned, Please Use the JSON.stringify method to build the JSON request. Updating this answer to include correct way for future visitors.

Shyju
  • 214,206
  • 104
  • 411
  • 497
  • 1
    -1 for leaving the hardcoded JSON string in the ajax request. – Darin Dimitrov Jun 13 '12 at 16:43
  • 1
    Yes, I mentioned it in my comment: the reason is that you left the hardcoded JSON string in the `data` parameter which doesn't properly encode. Also you left a controller action returning string which also is wrong. I see so many people doing this error that it is absolutely vital to me to point out this horrible mistake everytime I see such code. – Darin Dimitrov Jun 13 '12 at 16:45
  • @DarinDimitrov: Thanks for pointing it out. I updated my answer to include the correct way For Future visitor's reference. The OP's question has the action method which returns the string. I was helping to fix the ajax call issue only. Just out of curiousity, why is it **wrong** , if i return string from an action method (my scenario is like i just want to return only word)? – Shyju Jun 13 '12 at 16:52
  • 1
    No, it is wrong because when you return string you are not setting the correct `Content-Type` header. You should always return instances of action results. – Darin Dimitrov Jun 13 '12 at 16:54
  • @DarinDimitrov: Phil hacks says, you can use the string return type to return the string. http://stackoverflow.com/a/555026/40521. Isn't not going to return the content type as "text/plain" by default then ? – Shyju Jun 13 '12 at 16:58
  • Yes, it will be `text/plain` by default. But in this case you should not return a string. You should use a `ContentResult` to respect the pattern. Look at the accepted answer in the link you provided. It's much better than Phil Haack's. – Darin Dimitrov Jun 13 '12 at 16:59
  • @DarinDimitrov: OK . I gave up ! :) It was really worth defending ( :)) with you. Atleast i learned something new today ( and glad it is from the ASP.MVC master). Thanks alot for sharing. – Shyju Jun 13 '12 at 17:03
9

Never build JSON with string manipulations:

data: "{'id': '"+docId +"', 'filename': '"+fileName+"', 'description': '"+fileDescription+"'}",

That's absolutely horrible and wrong. You are not encoding anything. Suffice a quote in the description and everything will break. Always use a JSON parser when manipulating JSON

Like this:

$.ajax({
     type: "POST",
     url: "/OrderDetail/LoadModelData",
     contentType: "application/json; charset=utf-8",
     data: JSON.stringify({ 
         id: docId, 
         filename: fileName, 
         description: fileDescription 
     }),
     success: function (result) {
         alert("ok: "+ result.filename);
     },
     error: function (result) {
         alert('Oh no: '+ result.responseText);
     }
 });

The JSON.stringify method is natively built-in modern browsers. If you need to support legacy browsers you could include the json2.js script

Another mistake is your controller action signature. In ASP.NET MVC controller actions must return ActionResults, not strings:

[HttpPost]
public ActionResult LoadModelData(string id, string filename, string description)
{
    return Json(new { filename = filename });
}
Donnelle
  • 5,689
  • 3
  • 27
  • 31
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928