过去几晚我一直对我的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:
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 = "" });
答案 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处理 - 然后,在看到表单时,正在执行“提交”调用,该调用重定向回同一页面。
抱歉浪费每个人的时间。有一些非常有用的建议和许多实用的想法来解决我的问题。