开发者

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: true

By 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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜