More Ajax / MVC weirdness
I've been puzzling over some odd behaviour with my MVC2 project for the last few nights.
I have an MVC action result that accepts a project ID an开发者_JS百科d a complex Json object, looking like this:
[HttpPost]
public JsonResult AddStory(int projectid, Story story)
{
    try
    {
        Project prj = repository.Single(p => p.ID == projectid);
        //prj.Stories.Add(story);
        //repository.SaveChanges();
        return Json(new { Result = story });
    }
    catch (Exception ex)
    {
        ErrorSignal.FromCurrentContext().Raise(ex);
        return Json(new { Result = 0 });
    }
}
My jQuery code for sending the complex object looks like this so far (complex object has more properties than this, but am trying only these two for debugging reasons):
$.ajax({
    url: '/Project/1/AddStory',
    data: { Summary: myStory.Summary, Size: myStory.Size },
    dataType: 'json',
    processData: false,
    traditional: true,
    type: 'POST'
});
My problem is that no matter how I post this object; even if I send it to a different controller and action, the request never seems to hit the server and the page is automatically redirected to the following URL:
http://localhost:57932/Project/1/Board?story.Summary=Test+description&story.Size=8&story.Priority=2&story.Deadline=08%2F31%2F2010&story-owner=http%3A%2F%2Ftestaccount.myopenid.com
Firebug's console shows an error in jQuery.min.js with the right headers, but no POST or RESPONSE values.
I've tried looking at the traffic in Fiddler and I can see that the request headers appear well-formed:
Accept application/json, text/javascript, /
And there is definitely an object being sent in the query string. So what am I missing? I'm sure there has to be a simple reason why things are getting so borked.
Edit:
Routes (from Global.asax) are the following plus the default mapped route:
    routes.MapRoute(
        "Project",
        "Project/{projectid}/{action}/{id}",
        new { controller = "Project", action = "Index", id = "" });
Turns out the solution is simple. The ajax call in this current shape simply doesn't send any POST data due to processData = false setting. Change the jQuery to this:
$.ajax({
    url: '/Project/1/AddStory',
    data: { Summary: myStory.Summary, Size: myStory.Size },
    dataType: 'json',
    traditional: true,
    type: 'POST'
});
The jQuery API doco is a bit obtuse:
processData
Default: trueBy default, data passed in to the data option as an object (technically, anything other than a string) will be processed and transformed into a query string, fitting to the default content-type "application/x-www-form-urlencoded". If you want to send a DOMDocument, or other non-processed data, set this option to false.
My interpretation is that it it's false, $.ajax will not convert the data object as name value parameters. Not sure what it's used for, but setting it to false seems like a bad idea :)
I don't have your full source code, so it is difficult to say why you have request redirection from '/Project/1/AddStory' to the
http://localhost:57932/Project/1/Board?story.Summary=Test+description&...
T tried to reproduce your problem. I created a small MVC 2 aplication with the action AddStory in the controller Project which looks like yours:
[HttpPost]
public JsonResult AddStory (int projectid, Story story) {
    return Json (new {
        Result = story,
        myNewProjectid = projectid,
        myNewSummary = story.Summary + ". " + "Bla bla",
        myNewSize = story.Size + 20
    });
}
where Story class I declared just like folowing:
public class Story {
    public string Summary { get; set; }
    public int Size { get; set; }
}
I inserted the route like you posted and added following jQuery sctipt in the Index view of the Home controller:
jQuery(document).ready(function () {
    var myStory = { Summary: 'Test description', Size: 8 };
    $.ajax({
        url: '/Project/1/AddStory',
        data: { Summary: myStory.Summary, Size: myStory.Size },
        dataType: 'json',
        success: function (data, textStatus, xhr) {
            alert('myNewSummary="' + data.myNewSummary +
                  '", Result.Summary="' + data.Result.Summary +
                  '", Result.Size=' + data.Result.Size);
        },
        error: function (xhr, textStatus, errorThrown) {
            alert("error");
        },
        type: 'POST'
    });
});
The code work without any problem and produce the message box with the text myNewSummary="Test description. Bla bla", Result.Summary="Test description", Result.Size=8 how expected.
You can continue to use traditional: true if you receive problems with posting more complex data structures. The current test don't need the usage of traditional: true.
To make you easy for you to compare your code with my working eample I placed full Visual Studio 2010 project under http://www.ok-soft-gmbh.com/ForStackOverflow/MvcApplicationJson.zip. I hope this helps you quickly to find th error in your code and fix it.
i'd suggest you use $.post in stead
            var jsonbox = { Summary: myStory.Summary, Size: myStory.Size }
            $.post("/Project/1/AddStory", jsonbox, function doneit(data) {
                if (data.succes == true) {
                    //do something like return a message 'saved, all ok'
                } else {
                    /give an error.
                }
            }, "json");
i always use this style of action
    [HttpPost]
    public ActionResult SomeAction(int id, FormCollection collection) {
        try {
           //some code
        } catch (Exception e) {
            return Json(new { succes = false, error = "An error occured. Details: " + e.Message });
        }
        return Json(new { succes = true });
    }
$.post works good if you dont need anything fancy just a post, a variable to send and a function to execute when you get the result.
Ugh. PEBKAC issue.
Turns out the problem was because I'd previously had my input fields inside a set of <form> tags and jQuery was dutifully submitting my content - which doesn't need the projectId explicitly passed since that is part of the query string and is handled by MVC - and then, upon seeing the form, was actioning a "submit" call, which redirected back to the same page.
Sorry for wasting everyone's time. There was some really useful advice and a lot of practical ideas to troubleshoot my problem with.
 
         加载中,请稍侯......
 加载中,请稍侯......
      
精彩评论