更多Ajax / MVC怪异

时间:2010-08-16 08:28:39

标签: json asp.net-mvc-2 binding jquery

过去几晚我一直对我的MVC2项目的一些奇怪行为感到困惑。

我有一个MVC操作结果,它接受一个项目ID和一个复杂的Json对象,如下所示:

[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 });
    }
}

我发送复杂对象的jQuery代码到目前为止看起来像这样(复杂对象有比这更多的属性,但出于调试原因我只尝试这两个):

$.ajax({
    url: '/Project/1/AddStory',
    data: { Summary: myStory.Summary, Size: myStory.Size },
    dataType: 'json',
    processData: false,
    traditional: true,
    type: 'POST'
});

我的问题是无论我如何发布这个对象;即使我将其发送到不同的控制器和操作,请求似乎永远不会到达服务器,页面会自动重定向到以下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的控制台在jQuery.min.js中显示错误,其中包含正确的标题,但没有POST或RESPONSE值。

我已经尝试查看Fiddler中的流量,我可以看到请求标头看起来格式正确:

  

接受application / json,   text / javascript, /

在查询字符串中肯定会发送一个对象。那我错过了什么?我确信必须有一个简单的理由让事情变得如此沉重。

编辑:

路由(来自Global.asax)是以下加上默认的映射路由:

    routes.MapRoute(
        "Project",
        "Project/{projectid}/{action}/{id}",
        new { controller = "Project", action = "Index", id = "" });

4 个答案:

答案 0 :(得分:3)

原来解决方案很简单。由于processData = false设置,此当前形状的ajax调用不会发送任何POST数据。将jQuery更改为:

$.ajax({
    url: '/Project/1/AddStory',
    data: { Summary: myStory.Summary, Size: myStory.Size },
    dataType: 'json',
    traditional: true,
    type: 'POST'
});

jQuery API doco有点迟钝:

  

<强>过程数据
  默认值:true

     

默认情况下,数据传入数据   选项作为对象(技术上,   除了字符串以外的任何东西)   处理并转换为查询   字符串,适合默认值   内容类型   “应用程序/ x WWW的形式进行了urlencoded”。   如果要发送DOMDocument,或者   其他未处理的数据,设置此   选项为false。

我的解释是它是假的,$.ajax不会将数据对象转换为名称值参数。不知道它用于什么,但将其设置为假似乎是一个坏主意:)

答案 1 :(得分:1)

我没有您的完整源代码,因此很难说 为什么 您有从'/ Project / 1 / AddStory'请求重定向到< / p>

http://localhost:57932/Project/1/Board?story.Summary=Test+description&...

T试图重现你的问题。我在控制器AddStory中使用动作Project创建了一个小型MVC 2应用程序,它看起来像你的:

[HttpPost]
public JsonResult AddStory (int projectid, Story story) {
    return Json (new {
        Result = story,
        myNewProjectid = projectid,
        myNewSummary = story.Summary + ". " + "Bla bla",
        myNewSize = story.Size + 20
    });
}

其中Story类我声明如下:

public class Story {
    public string Summary { get; set; }
    public int Size { get; set; }
}

我在jQuery控制器的Index视图中插入了您发布的路线,并在Home sctipt后添加:

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'
    });
});

代码工作没有任何问题,并生成带有文本myNewSummary="Test description. Bla bla", Result.Summary="Test description", Result.Size=8预期的消息框。

如果您在发布更复杂的数据结构时遇到问题,可以继续使用traditional: true。当前测试不需要使用traditional: true

为了方便您将代码与我的工作示例进行比较,我在http://www.ok-soft-gmbh.com/ForStackOverflow/MvcApplicationJson.zip下放置了完整的Visual Studio 2010项目。我希望这可以帮助您快速找到代码中的错误并进行修复。

答案 2 :(得分:0)

我建议您使用$.post代替

            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");

我总是使用这种行动方式

    [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效果很好,如果你不需要任何花哨的帖子,一个要发送的变量和一个在你得到结果时执行的函数。

答案 3 :(得分:0)

唉。 PEBKAC问题。

原来问题是因为我之前在一组<form>标签中输入了我的输入字段,jQuery正在尽职地提交我的内容 - 这不需要显式传递projectId,因为这是查询字符串由MVC处理 - 然后,在看到表单时,正在执行“提交”调用,该调用重定向回同一页面。

抱歉浪费每个人的时间。有一些非常有用的建议和许多实用的想法来解决我的问题。