将JSON发布到Controller

时间:2010-05-18 21:28:08

标签: asp.net asp.net-mvc json controller

我的控制器里有这个:

    [HttpPost]
    public void UpdateLanguagePreference(string languageTag)
    {
        if (string.IsNullOrEmpty(languageTag))
        {
            throw new ArgumentNullException("languageTag");
        }

        ...
    }

让这个jQuery代码POST到控制器:

           jQuery.ajax({
                type: 'POST',
                url: '/Config/UpdateLanguagePreference',
                contentType: 'application/json; charset=utf-8',
                data: '{ "languageTag": "' + selectedLanguage + '" }'
            });

然而,当我尝试代码时,我收到错误:

Server Error in '/' Application.
Value cannot be null.
Parameter name: languageTag

有什么问题?这不是如何将JSON POST到MVC控制器?我可以使用Fiddler检查POST,看看请求是否正确。出于某种原因,UpdateLanguagePreference()获取空字符串或空字符串。

4 个答案:

答案 0 :(得分:7)

非常重要的警告,即使在MVC3中,关于MVC3的工作方式。

如果你传递了像say:

这样的对象
​{
    Test: 'Hi'
}

接收类是:

public class MyModel
{
    public string Test { get; set; }
}

使用接收控制器方法,如:

[HttpPost]
public JsonResult Submit(MyModel model)
{
    . . .

它会起作用。但是,如果您的Controller方法具有非常小的,看似无害的变化:

[HttpPost]
public JsonResult Submit(MyModel test)
{
    . . .

它会失败。这是因为MVC框架将JSON消费到如上所述的Dictionary中,并且看到其中一个参数具有相同的名称,不区分大小写,作为其中一个键(" Test" /&#34 ;试验&#34)。然后它将字符串值" Hi",分配给Test,并将其传递给此参数" test"即使这显然不是作者的意图。

最有问题的是,框架在尝试将字符串分配给MyModel类型的arg时不会抛出错误,这至少可以为您提供有关错误的线索。它没有看到这是错误的类型和它的替代行为的后退(如果这些arg /属性在名称上不匹配,它会追求)。它只是默默地失败并为你的论点指定null,让你不知道发生了什么。

我反复遇到这个问题,最后发现了让事情似乎随机停止在MVC中工作的故障...我希望这可以帮助其他人。

由于此Action参数的任何合理名称都是可能合理的属性名称(模型,数据等),并且由于它不区分大小写,因此在不编写自己的模型绑定程序的情况下防止它的最安全方法是标准化在一个,疯狂的,非常不可能有一个属性名称的参数名称,如:

[HttpPost]
public JsonResult Submit(MyModel _$_$twinkleTwinkleLittleFuckIt)
{

但是如果你有时间,那么修复ModelBinder / JsonValueProviderFactory就可以冒险,而不是十年内那个奇怪的bug,没有人可以到达底层。

答案 1 :(得分:1)

... HMM

我这样做

 $.post(target,
         {
             "ProblemId": id,
             "Status": update
         }, ProcessPostResult);

public class ProblemReportUpdate
    {
        public int ProblemId { get; set; }
        public string Status { get; set; }
    }

 [HttpPost]
 public ActionResult UpdateProblemReport(ProblemReportUpdate update)

目标由

设定
var target = '<%=Url.Action("UpdateProblemReport", "ProblemReport") %>

答案 2 :(得分:1)

您正在发布字符串而不是JSONified对象。

数据:'{“languageTag”:“'+ selectedLanguage +'”}'

应该是

数据:{“languageTag”:selectedLanguage}

并确保在ajax调用的范围内定义selectedLanguage。

答案 3 :(得分:1)

当你给jQuery的$ .ajax()函数一个javascript对象形式的数据变量时,它实际上将它转换为一系列键/值对,并以这种方式将它发送到服务器。当你发送字符串化的json对象时,它不是那种形式,mvc / mvc2中的标准模型绑定器不会删除它。

如果你想以这种方式发送帖子数据,那么你几乎就在那里。您需要在MVC2 Futures / MVC3 Beta中找到JsonValueProviderFactory类。请查看以下链接以获取更多信息:

http://haacked.com/archive/2010/04/15/sending-json-to-an-asp-net-mvc-action-method-argument.aspx

...我自己实现这个时使用的另一个链接更多地讨论了将JsonValueProviderFactory类引入你的应用程序,但我找不到它的生命。