Как заставить контроллер принимать данные постов из тела, а также URL в MVC 6 ASP.NET 5

В настоящее время я пытаюсь написать контроллер в MVC 6, способный принимать данные из почтового запроса. Проблема заключается в том, что в зависимости от клиента (который не всегда является веб-браузером) данные могут вводиться либо в виде пар ключ-значение в URL-адресе запроса, либо в виде JSON в теле запроса.

В настоящее время этот метод работает для приема данных из URL:

[HttpPost]
public async Task<CaptureResponse> CaptureData(CaptureInfo capture) {
    ...
}

После большого количества проб и ошибок (и ответов переполнения стека) я понял, что [FromBody] Атрибут указывает связующему модели искать в теле запроса, что требуется сейчас, потому что MVC 6 объединяет WebApi и стандартный MVC вместе. Следующий код анализирует данные из JSON в теле формы:

[HttpPost]
public async Task<CaptureResponse> CaptureData([FromBody] CaptureInfo capture) {
   ...
}

Для простоты я хотел бы как-то объединить их вместе, чтобы связыватель модели дал мне данные в одной переменной параметра. Пока что единственный способ, которым я могу получить данные в одном и том же действии, - это указать два параметра, один для URL-адреса и один для тела, и выполнить некоторую нулевую проверку для каждого из них следующим образом:

[HttpPost]
public async Task<CaptureResponse> CaptureData(CaptureInfo capture, [FromBody] CaptureInfo bodyCapture) {
    if (bodyCapture != null) {
        if (bodyCapture.RequiredProperty1!= null
        && bodyCapture.RequiredProperty2!= null) {
            capture = bodyCapture;
        }
    }
    ...
}

Я попытался указать несколько свойств перед входным атрибутом, как это:

[HttpPost]
public async Task<CaptureResponse> CaptureData(CaptureInfo [FromQuery][FromRoute][FromForm][FromBody] capture) {
    ...
}

Но это не работает. Есть идеи, если что-то подобное возможно?

2 ответа

Насколько я знаю, это просто невозможно. Конечно, вы можете попробовать использовать обходные пути, в основном выполняя все запросы самостоятельно. Звучит не очень хорошо, правда?

Если вы действительно хотите, чтобы все было по-вашему, я считаю, что лучший подход - это иметь две разные конечные точки в контроллере и частный метод для фактической обработки. Или, возможно, даже извлечь этот метод в дополнительный уровень абстракции с классом (ами) BlaBlaService (в вашем случае, вероятно, CaptureService), ответственным за всю грязную работу. Иногда имеет смысл отделить ваш уровень контроллеров от бизнес-логики - например, для целей тестирования.

PS: Ваша идея очень похожа на ту, которая была в старые добрые времена.NET и PHP, и поверьте мне, эта конкретная идея не сделала те времена хорошими. Вы знаете, MVC во многом похож на REST-подобный подход, поэтому каждая конечная точка вашего контроллера должна быть выделена для отдельной функции и подчиняться единому и унифицированному "интуитивному" протоколу.

"Интуитивно понятный" способ отправки данных в POST-запрос для разработчиков, знакомых с REST, - через тело запроса. Я предлагаю вам рассмотреть возможность использования этого подхода как единственного.

Вам нужно использовать Request.Form

лайк:

   string username = HttpContext.Current.Request.Form.GetValues("key1")[0].ToString();
    string password = HttpContext.Current.Request.Form.GetValues("key2")[0].ToString();
    string something = HttpContext.Current.Request.Form.GetValues("key3")[0].ToString();
Другие вопросы по тегам