#asp.net-mvc #xml #json #rest #loose-coupling
#asp.net-mvc #xml #json #rest #слабая связь
Вопрос:
Я создаю REST API в ASP.NET MVC. Я хочу, чтобы формат запроса и ответа был JSON или XML, однако я также хочу упростить добавление другого формата данных и сначала создать просто XML, а затем добавить JSON.
В принципе, я хочу указать всю внутреннюю работу запросов GET / POST / PUT / DELETE моего API, не задумываясь о том, в каком формате пришли данные или в каком виде они останутся, и я мог бы легко указать формат позже или изменить его для каждого клиента. Итак, один парень мог бы использовать JSON, другой парень мог бы использовать XML, один парень мог бы использовать XHTML. Тогда позже я мог бы добавить и другой формат, не переписывая тонну кода.
Я не хочу добавлять кучу операторов if / then в конце всех моих действий и определять формат данных, я предполагаю, что есть какой-то способ, которым я могу это сделать, используя интерфейсы или наследование или тому подобное, просто не уверен, что это лучший подход.
Ответ №1:
Сериализация
The ASP.NET для этого предназначен конвейер. Действия вашего контроллера возвращают клиенту не результат, а скорее результирующий объект ( ActionResult
), который затем обрабатывается на дальнейших этапах в ASP.NET конвейер. Вы можете переопределить ActionResult
класс. Обратите внимание, что FileResult, JsonResult, ContentResult
и FileContentResult
встроены начиная с MVC3.
В вашем случае, вероятно, лучше всего возвращать что-то вроде RestResult
объекта. Теперь этот объект отвечает за форматирование данных в соответствии с запросом пользователя (или любыми другими дополнительными правилами, которые у вас могут быть):
public class RestResult<T> : ActionResult
{
public override void ExecuteResult(ControllerContext context)
{
string resultString = string.Empty;
string resultContentType = string.Empty;
var acceptTypes = context.RequestContext.HttpContext.Request.AcceptTypes;
if (acceptTypes == null)
{
resultString = SerializeToJsonFormatted();
resultContentType = "application/json";
}
else if (acceptTypes.Contains("application/xml") || acceptTypes.Contains("text/xml"))
{
resultString = SerializeToXml();
resultContentType = "text/xml";
}
context.RequestContext.HttpContext.Response.Write(resultString);
context.RequestContext.HttpContext.Response.ContentType = resultContentType;
}
}
Десериализация
Это немного сложнее. Мы используем Deserialize<T>
метод базового класса контроллера. Пожалуйста, обратите внимание, что этот код не готов к работе, потому что чтение всего ответа может переполнить ваш сервер:
protected T Deserialize<T>()
{
Request.InputStream.Seek(0, SeekOrigin.Begin);
StreamReader sr = new StreamReader(Request.InputStream);
var rawData = sr.ReadToEnd(); // DON'T DO THIS IN PROD!
string contentType = Request.ContentType;
// Content-Type can have the format: application/json; charset=utf-8
// Hence, we need to do some substringing:
int index = contentType.IndexOf(';');
if(index > 0)
contentType = contentType.Substring(0, index);
contentType = contentType.Trim();
// Now you can call your custom deserializers.
if (contentType == "application/json")
{
T result = ServiceStack.Text.JsonSerializer.DeserializeFromString<T>(rawData);
return resu<
}
else if (contentType == "text/xml" || contentType == "application/xml")
{
throw new HttpException(501, "XML is not yet implemented!");
}
}
Комментарии:
1. В части сериализации вверху, как данные передаются методам сериализации? Кроме того, что следует использовать вместо ReadToEnd () внизу? Спасибо за вашу помощь.
2. Привет, Райан, метод сериализации находится в том же классе и обращается к
Result
объекту, который является частьюActionResult
. Вместо того, чтобы использовать простойReadToEnd
, я бы прочитал вручную и посчитал байты, чтобы убедиться, что запрос не превышает определенного приложением предела.
Ответ №2:
Просто хотел включить это здесь для справки, но я обнаружил, что с помощью ASP.NET MVC, возможно, не лучший способ сделать это:
Windows Communication Foundation (WCF) предоставляет унифицированную модель программирования для быстрого создания сервис-ориентированных приложений, которые взаимодействуют через Интернет и на предприятии
Сегодня разработчики веб-приложений сталкиваются с новыми проблемами, связанными с предоставлением данных и сервисов. Облако, переход на устройства и переход к браузерным фреймворкам, таким как jQuery, предъявляют все возрастающие требования к предоставлению такой функциональности удобным для Интернета способом. Предложение WCF по веб-API ориентировано на предоставление разработчикам инструментов для создания простых, но мощных приложений, которые работают в этом новом мире. Для разработчиков, которые хотят пойти дальше, чем просто предоставлять доступ через HTTP, наш API позволит вам получить доступ ко всему богатству HTTP и применить ограничения RESTful при разработке вашего приложения. Эта работа является развитием функций HTTP / ASP.NET AJAX, уже представленных в .Net 4.0.
Однако я не буду выбирать это в качестве ответа, потому что это фактически не отвечает на вопрос, несмотря на то, что это маршрут, которым я собираюсь воспользоваться. Я просто хотел поместить это здесь, чтобы быть полезным для будущих исследователей.
Комментарии:
1. Я видел кучу сообщений здесь, на SO, где люди жалуются, что у вас нет полного контроля при использовании WCF. В частности, настраиваемая обработка ошибок, похоже, является серьезной проблемой.