2010-05-18 4 views
5

У меня есть это в моем контроллере:Проводка JSON контролера

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

     ... 
    } 

И есть этот код POSTING Jquery к контроллеру:

  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 

В чем проблема? Разве это не как POST JSON для контроллера MVC? Я могу проверить POST с помощью Fiddler и убедиться, что запрос правильный. По какой-то причине UpdateLanguagePreference() получает пустую или пустую строку.

ответ

1

хмм ....

Я делаю это

$.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") %> 
1

Вы отправляете строку, а не объект JSONified.

данные: { "languageTag": "'+ selectedLanguage + '"}'

должен быть

данные: { "languageTag": selectedLanguage}

И убедитесь, что selectedLanguage определяется в рамках вашего вызова ajax.

+0

Хм, это на самом деле не так. Объектом JSONified является строка. Между строкой, которую я отправляю, и JSONified-объектом с членом с именем «languageTag» нет. – JamesBrownIsDead

+0

@JamesBrownIsDead - На самом деле, как я понимаю, есть разница. Взгляните на мой ответ ниже. – kdawg

1

Когда вы передаете функцию $ .ajax() функции jQuery в форме объекта javascript, она фактически переводит ее в пару пар ключ/значение и отправляет ее на сервер таким образом. Когда вы отправляете строковый объект json, он не находится в этой форме, и стандартное связующее устройство в mvc/mvc2 не будет его обрезать.

Если вы хотите отправить данные сообщения таким образом, то вы почти там. Вам нужен класс JsonValueProviderFactory, найденный в MVC2 Futures/MVC3 Beta. Взгляните на следующие ссылки для получения дополнительной информации:

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

... есть еще одна ссылка я использовал при реализации этого сам, что говорил больше о результате чего JsonValueProviderFactory класс в приложение, но я не могу найти это для меня.

7

Очень важно предупредить, даже в MVC3, о том, как работает MVC3.

Если вы передаете объект, как говорят:

​{ 
    Test: 'Hi' 
} 

И принимающий класс:

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

С методом контроллера принимающем как:

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

Он будет работать. Но если ваш метод контроллера имеет это очень незначительное, казалось бы, безобидное изменение:

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

Это не удастся. Это связано с тем, что структура MVC использует JSON в словаре, как упоминалось выше, и видит, что один из параметров имеет одно и то же имя, не учитывающее регистр, как один из его ключей («Тест»/«тест»). Затем он берет строковое значение «Привет», назначенное Test, и передает это аргументу «тест», хотя это явно не то, что автор намеревался.

Что является наиболее проблематичным в этом вопросе, так это то, что в фреймворке не возникает ошибка, пытающаяся присвоить строку аргументу типа MyModel, что, по крайней мере, даст вам представление о том, что пошло не так. Он не видит, что это был неправильный тип и отказ от его альтернативного поведения (которое он преследовал бы, если бы эти аргументы/свойства не соответствовали имени). Он просто терпит неудачу, и присваивает значение null вашему аргументу, оставляя вас без подсказки относительно того, что происходит.

Я неоднократно сталкивался с этой проблемой и, наконец, обнаружил сбой, который заставляет вещи случайно перестать работать в MVC ... Надеюсь, это поможет кому-то другому.

Поскольку любое разумное имя для этого аргумента действия является потенциально разумным именем свойства (модель, данные и т. Д.), А так как оно нечувствительно к регистру, самый безопасный способ предотвратить его без написания собственного связующего устройства - стандартизировать его, сумасшедший, очень-вряд ли к когда-либо-свойство-имя-быть имя аргумента, например:

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

Но если у вас есть время, исправить ModelBinder/JsonValueProviderFactory так что 0 рисков вместо того, что один странного ошибка в течение десятилетия никто не может получить до дна.

+0

Он работает, как вы говорите, но если у меня есть список объектов внутри модели, он не связывается. Он производит любой пустой список – Bryida

Смежные вопросы