#asp.net #asp.net-mvc-3 #rest
#asp.net #asp.net-mvc-3 #rest
Вопрос:
Мне интересно, существует ли лучшая практика для создания REST API с ASP.NET MVC 3? На данный момент я подумываю о создании контроллера для каждой версии REST API. Например, до сих пор у меня:
public class V1Controller : Controller
{
public V1Controller()
{
}
public ActionResult GetUser(string userId, IUserRepository userRepostory)
{
//code to pull data and convert to JSON string
return View("Results");
}
public ActionResult GetUsersByGroup(string groupId, IUserRepository userRepostory)
{
//code to pull data and convert to JSON string
return View("Results");
}
}
Затем для представлений я перезаписываю _ViewStart.cshtml, чтобы удалить макет, и тогда у меня есть Results.cshtml, который просто выводит данные, отформатированные в действии контроллера, прямо сейчас JSON. Наличие каждого отдельного вызова REST в одном контроллере кажется немного перебором, но это лучший способ, который я могу придумать, чтобы я мог поддерживать чистоту отдельных версий API, чтобы, когда дело дойдет до создания версии 2 API, я мог создать V2Controller и не ломать существующий API, чтобы дать людям время переключиться на новый API.
Есть ли лучший способ создать REST API с ASP.NET MVC 3?
Комментарии:
1. Кажется, вы хотите спросить о управлении версиями. Я думаю,
V1Controller
что это не очень хорошая практика. Вы объединили все версии в однуControllers
в проекте MVC. Я думаю, что версия должна быть тегом / форком из истории управления версиями. Это не должно быть проблемой для обслуживания только службы REST, но MVC содержит веб-сайт REST. Итак, как я могу опубликовать управление версиями REST, в то время как веб-сайт использует только последнюю версию REST? Затем я создаю 2 проекта MVC, один для веб-сайта, другой для службы REST (но почему не WCF?). MVC должен обрабатывать оба варианта в проекте, я снова возвращаюсь к первоначальной мысли!
Ответ №1:
Я смог найти достойное решение, используя использование областей MVC.
Во-первых, я хотел, чтобы мой API соответствовал этому определению URL:
http://[website]/[major_version]_[minor_version]/{controller}/{action}/...
Я также хотел разбить разные версии на отдельные файлы проекта и использовать одни и те же имена контроллеров в каждой версии:
"../v1_0/Orders/ViewOrders/.." => "../v2_3/Orders/ViewOrders/.."
Я поискал и нашел работоспособное решение с использованием областей MVC.
Я создал новый проект в своем решении под названием «Api.Controllers.v1_0» и в качестве теста поместил туда файл SystemController.cs:
using System.Web.Mvc;
namespace Api.Controllers.v1_0
{
public class SystemController : Controller
{
public ActionResult Index()
{
return new ContentResult() {Content = "VERSION 1.0"};
}
}
}
Затем я добавил файл v1_0AreaRegistration.cs:
using System.Web.Mvc;
namespace Api.Controllers.v1_0
{
public class v1_0AreaRegistration : AreaRegistration
{
public override string AreaName
{
get{ return "v1_0";}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"v1_0",
"v1_0/{controller}/{action}/{id}",
new { controller = "System", action = "Index", id = UrlParameter.Optional }
);
}
}
}
Я проделал те же шаги, что и выше, для проекта «..v1_1» с соответствующими файлами внутри, добавил проекты в качестве ссылок в мой MVC-проект «Api.Web» и был выключен и запущен.
Комментарии:
1. также я бы добавил, что следует рассмотреть возможность наследования контроллеров более высокой версии от контроллеров более низкой версии, чтобы им нужно было только реализовать поведение, которое изменилось, вместо дублирования поведения. также рассмотрите возможность использования того же подхода для объектов модели.
Ответ №2:
Если все, что вы возвращаете, это JSON, вам не нужно представление. Возврат Jusr
new JsonResult(){Data = Data};
Загляните сюда.
Также с точки зрения управления версиями версии могут быть реализованы как разные контроллеры или как дополнительные методы в одном контроллере. Но из вашего вопроса неясно, не зная, зачем вам понадобятся версии и почему вашим клиентам (которые, я полагаю, являются браузерами) нужно знать об управлении версиями.
Комментарии:
1. Ну, «клиентами» являются все, кто использует API. Возможность иметь версии объясняется тем, что я вношу изменения, которые заставляют меня менять API. Если у меня будут версии API, это поможет мне свести на нет возможность взлома всех, кто использует более старую версию API (не 100%, но значительное большинство).
2. Управление версиями имеет решающее значение в корпоративном сценарии. это практически необходимо для нескольких сред с несколькими клиентами, распределенных по предприятию с несколькими серверами в ферме.
Ответ №3:
Контроллер, подобный тому, который вы опубликовали в своем примере кода, должен всегда сохранять, например, те методы, которые у вас есть сейчас GetUsersByGroup()
, с той же сигнатурой. Я не понимаю, как может существовать другая версия этого метода.
Входными данными являются group и repository (которые, я полагаю, поступают из DI). На выходе получается список пользователей в формате JSON. Это все, что имеет значение для пользователей API. То, что вы делаете внутри этого метода, никого не касается.
Вам следует больше думать о вводах и выводах. Вам не следует изменять подписи существующих действий, если это действительно не необходимо.
Подумайте о классе контроллера с точки зрения реализации интерфейса. У вас есть интерфейс, и класс контроллера является его реализацией (я имею в виду, что вам не нужно его иметь, просто подумайте об этом таким образом). Вы редко будете изменять интерфейс после того, как один или несколько классов его реализуют. Но вы могли бы добавить к нему методы. И это требует только изменений в реализующих классах — это не нарушает функциональность API, и все, кто его использует, смогут продолжать его использовать.