Как заставить контроллер принимать данные постов из тела, а также 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();