ASP.Net MVC: отправка JSON в контроллер - PullRequest
9 голосов
/ 26 января 2010

Я хочу иметь возможность отправлять JSON в отличие от стандартных QueryStrings при создании сообщения для моих контроллеров в ASP.Net MVC. У меня все в порядке с интерфейсом (сборка и отправка моих объектов JSON).

Проблема на стороне контроллера, где ModelBinder по умолчанию, поставляемый с платформой MVC, не поддерживает это.

Я видел комбинацию способов обойти это, один из них - применить фильтр, который принимает объект в качестве параметра, использует библиотеку JSON для десериализации его и добавляет его к параметрам действия. Это не идеально.

Другой, лучший способ - использовать пользовательское связующее для моделей. Все те, которые я видел, предполагают, что у вас будет только одна модель, и это будет класс, а не переменная. Если у вас их несколько, они ломаются.

Кто-нибудь еще сталкивался с этим? У меня была одна идея, если бы я мог просто переопределить, как MVC работает с FormCollection, и перехватывать там, добавляя значения в коллекцию сам и надеясь, что MVC сделает все остальным в обычном режиме. Кто-нибудь знает, возможно ли это?

Ключевой вопрос, я думаю, заключается в том, что моя проблема не в связывании, потому что мои модели представлений ничем не отличаются от того, где они были раньше. Проблема заключается в получении значений из JSON Post.

Если я прав, MVC получает значения из QueryString и помещает их в коллекцию форм, которая затем используется для ModelBinding. Так не должен ли правильный метод изменить способ назначения FormCollection?

Пример действия:

public ActionResult MyFirstAction(Int32 ID, PersonObject Person, ClassObject ClassDetails)
{
//etc
}

Обычное связывание работает, JSON - нет, и все примеры связывателей моделей также не будут работать. Мое лучшее решение на данный момент - преобразовать объект в словарь и зациклить каждый параметр и сопоставить его. Не кажется идеальным.

1 Ответ

8 голосов
/ 26 января 2010

Я использую привязку пользовательской модели для JSON, например:

public class JsonModelBinder<T> : IModelBinder {
    private string key;

    public JsonModelBinder(string requestKey) {
        this.key = requestKey;
    }

    public object BindModel(ControllerContext controllerContext, ...) {
        var json = controllerContext.HttpContext.Request[key];
        return new JsonSerializer().Deserialize<T>(json);
    }
}

А затем подключите его в Global.asax.cs так:

ModelBinders.Binders.Add(
    typeof(Product),
    new JsonModelBinder<Product>("ProductJson"));

Подробнее об этом можно прочитать здесь: Наследование является злом: эпическая ошибка DataAnnotationsModelBinder

EDIT

JsonModelBinder должен использоваться с параметром действия контроллера, указанным только для Product. Int32 и ClassObject должны возвращаться к DefaultModelBinder. Вы испытываете другой результат?

...