Різниця між ApiController і контролером в ASP.NET MVC


343

Я бавився з ASP.NET MVC 4 beta і зараз бачу два типи контролерів: ApiControllerі Controller.

Мене мало бентежить, в яких ситуаціях я можу вибрати конкретний контролер.

Наприклад: Якщо я хочу повернути перегляд, тоді я повинен використовувати ApiControllerабо звичайний Controller? Мені відомо, що веб-API WCF тепер інтегрований у MVC.

Оскільки зараз ми можемо використовувати обидва контролери, може хтось, будь ласка, вкажіть, у яких ситуаціях звернутися за відповідним контролером.


23
Важливо: ASPNET Core "злився", ApiControllerі Controllerтому, якщо ви використовуєте новіший .NET, вам більше не потрібно турбуватися про ApiController - docs.microsoft.com/en-us/aspnet/core/tutorials/first-web- api
Simon_Weaver

2
Рада, що вони зробили! Я передбачив це довгий час тому, як prideparrot.com/blog/archive/2012/10/asp_net_mvc_vs_webapi
VJAI

Відповіді:


356

Використовуйте Controller, щоб надати звичайні подання. Дія ApiController повертає лише дані, які серіалізуються та надсилаються клієнту.

ось посилання

Цитата:

Примітка Якщо ви працювали з ASP.NET MVC, то ви вже знайомі з контролерами. Вони працюють аналогічно у Web API, але контролери в Web API походять від класу ApiController замість класу Controller. Перша основна відмінність, яку ви помітите, полягає в тому, що дії на контролерах Web API не повертають представлення даних, вони повертають дані.

ApiControllers спеціалізуються на поверненні даних. Наприклад, вони дбають про прозору серіалізацію даних у потрібний клієнтом формат. Крім того, вони дотримуються іншої схеми маршрутизації за замовчуванням (як у: зіставлення URL-адрес на дії), надаючи API, повний REST за умовами.

Ви, ймовірно, можете зробити що-небудь, використовуючи контролер замість ApiController з деяким (?) Ручним кодуванням. Зрештою, обидва контролери будуються на основі ASP.NET. Але наявність API, повного REST, є настільки поширеною вимогою сьогодні, що WebAPI був створений для спрощення реалізації такого API.

Вибирати між цими двома проблемами досить просто: якщо ви пишете HTML-додаток для веб / Інтернет / інтранет - можливо, з випадкових AJAX дзвінків, що повертають json туди-сюди, - дотримуйтесь MVC / Controller. Якщо ви хочете надати в систему інтерфейс, керований даними / REST-ful, перейдіть до WebAPI. Звичайно, ви можете комбінувати обидва, виконуючи дзвінки AJAX ApiController на сторінці MVC.

Щоб навести приклад із реального світу: я зараз працюю з ERP-системою, яка надає найвищий API для своїх об'єктів. Для цього API WebAPI був би хорошим кандидатом. У той же час система ERP забезпечує веб-додаток із високим рівнем AJAX, який можна використовувати для створення запитів для API REST-ful. Сам веб-додаток може бути реалізований як додаток MVC, використовуючи WebAPI для отримання метаданих тощо.


9
Примітка: оскільки ваші дані будуть надсилатись через провід, яким чином вони будуть форматовані? Спосіб форматування даних, який повертає ApiController, визначається узгодженням вмісту та посиланням GlobalConfiguration.Configuration.Formatters ...: blogs.msdn.com/b/kiranchalla/archive/2012/02/25/…
Тім Ловелл-Сміт

1
Чи правильно сказати, що Web API є загальною платформою для веб-сайтів, мобільних пристроїв тощо? і ми могли б використовувати Бібліотеку класів замість Web API?
Імад Алазані

Дякую @ TimLovell-Smith за вашу замітку, оскільки для мене Андре не відповідає на запитання: оскільки Контролер також може повертати дані, це не пояснює, чому ApiController існує і є корисним.
JYL

2
@JYL Я доповнив свою відповідь, щоб надати більш детальну інформацію.
Андре Локер

2
Я насправді не розумів, коли ви сказали "надання звичайного API на REST" . Як це забезпечує API REST-ful? Чи не залежить від того, які дані ви повертаєте з API? У контролері немає нічого, що змушує (або навіть полегшує) API бути REST-ful.
Наваз

192

Що б ви краще писали та підтримували?

ASP.NET MVC

public class TweetsController : Controller {
  // GET: /Tweets/
  [HttpGet]
  public ActionResult Index() {
    return Json(Twitter.GetTweets(), JsonRequestBehavior.AllowGet);
  }
}

Веб-API ASP.NET

public class TweetsController : ApiController {
  // GET: /Api/Tweets/
  public List<Tweet> Get() {
    return Twitter.GetTweets();
  }
}

6
Це добре, але ApiController - це більше, ніж просто серіалізація JSON. Він також дбає про перегляд запиту та повернення XML, якщо це тип прийняття.
Джейк Альмер

10
Якщо ви використовуєте ядро ​​asp.net, усі вони походять від Controllerкласу.
Tân

2
Це здається старими прикладами. Зараз нам не потрібно хвилюватися ApiControllerлише за : Controllerтвори, чи можете ви також додати новий приклад контролера крапкового ядра
Ashish

@AshishKamble, замість ApiController, тепер використовується ControllerBase.
Володимир Шиянов

Чесно кажучи, я вважаю за краще Json()версію. Це чіткіше і чіткіше. Мені не подобається багато чорної магії, намагаючись зрозуміти, як мій код відповість на запит.
Їжак

27

Мені подобається те, що MVC6 ASP.NET Core об'єднав два шаблони в один, бо мені часто потрібно підтримувати обидва світи. Хоча це правда, що ви можете налаштувати будь-який стандартний MVC Controller(та / або розробити свої власні ActionResultкласи), щоб діяти та вести себе так само, як ApiController, але це може бути дуже важко підтримувати та перевіряти: на додаток до цього, використовуючи методи Controllers, що повертаються ActionResultзмішаними з іншими повернення необроблених / серіалізованих / IHttpActionResultданих може бути дуже заплутаним з точки зору розробника, особливо якщо ви не працюєте самотнім і вам потрібно привести інших розробників до швидкості з використанням гібридного підходу.

Найкраща методика, з якою я зайшов, щоб мінімізувати цю проблему в непрофільних веб-додатках ASP.NET - це імпорт (і правильна настройка) пакету веб-API у веб-додаток на базі MVC, тому я можу мати найкраще з обох світи: Controllersдля переглядів, ApiControllersдля даних.

Для цього вам потрібно зробити наступне:

  • Встановіть наступні пакети Web API за допомогою NuGet: Microsoft.AspNet.WebApi.Coreі Microsoft.AspNet.WebApi.WebHost.
  • Додайте до себе один або кілька ApiControllers /Controllers/ папки .
  • Додайте до папки такий файл WebApiConfig.cs/App_Config/ :

using System.Web.Http;

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API routes
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }
}

Нарешті, вам потрібно буде зареєструвати вищевказаний клас у вашому класі запуску (або Startup.csабоGlobal.asax.cs , залежно від того, ви використовуєте шаблон запуску OWIN чи ні).

Startup.cs

 public void Configuration(IAppBuilder app)
 {
    // Register Web API routing support before anything else
    GlobalConfiguration.Configure(WebApiConfig.Register);

    // The rest of your file goes there
    // ...
    AreaRegistration.RegisterAllAreas();
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);

    ConfigureAuth(app);
    // ...
}

Global.asax.cs

protected void Application_Start()
{
    // Register Web API routing support before anything else
    GlobalConfiguration.Configure(WebApiConfig.Register);

    // The rest of your file goes there
    // ...
    AreaRegistration.RegisterAllAreas();
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);
    // ...
}

Цей підхід - разом із його плюсами та мінусами - далі пояснюється у цій публікації, яку я написав у своєму блозі.


1
Гарна річ. але ця функціональність вже вбудована в vs2015. якщо ви створите проект webapi asp.net, він автоматично виконає весь код пластини котла для вас.
suomi-dev

@Darkseal Ви можете, будь ласка, докладно розібратися з питанням "це може бути дуже важко утримувати і тестувати"? (Я прочитав вашу публікацію в блозі) Я використовував WebAPI2 і мені подобається, як це працює. Однак я не можу визначити "справжню велику користь", окрім того, що це "загальний спосіб робити речі". Мати класичні контролери MVC, що повертають "вручну" серіалізовані рядки, досить просто. Додавання комутатора json / xml за допомогою дієслова http Accept не займе багато. Все, що можна перетворити на приємний корисний метод. Дякую.
ValGe

2
@ValGe, див. Відповідь @ manish-jain вище. Коротше кажучи, Controllerповернути серіалізовану рядок Json, обгорнуту всередині ActionResult, безумовно, важче перевірити та мати, ніж ApiControllerяку можна встановити для прямого повернення списку [Serializable]елементів. Будь-який метод тестування було б набагато простіше написати, тому що вам не доведеться де-серіалізувати кожен раз вручну: те ж саме можна сказати і для майже будь-якої завдання системної інтеграції з ASP.NET або іншими структурами. Controllersчудові, але ApiControllersкраще підходять для завдань RESTful, принаймні в .NET Framework 4.x
Darkseal

1

Кожен метод у веб-API повертає дані (JSON) без серіалізації.

Однак, щоб повернути дані JSON в контролери MVC, ми встановимо повернений тип результату дії на JsonResult і зателефонуємо на наш об’єкт методом Json, щоб переконатися, що він упакований у JSON.


1

Основна відмінність полягає в тому, що Web API - це послуга для будь-якого клієнта, будь-яких пристроїв, а контролер MVC обслуговує лише свого клієнта. Те саме, що це платформа MVC.


-1

Вирішити між цими двома проблемами досить просто: якщо ви пишете HTML-додаток для веб / інтернету / інтрамережі - можливо, з випадкових AJAX дзвінків, що повертають json туди-сюди - дотримуйтесь MVC / Controller. Якщо ви хочете надати в систему інтерфейс, керований даними / REST-ful, перейдіть до WebAPI. Звичайно, ви можете комбінувати обидва, виконуючи дзвінки AJAX ApiController на сторінці MVC. В основному контролер використовується для mvc, а api-контролер - це для Rest-API, ви можете використовувати обидва в тій же програмі, що вам потрібно

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.