Неатрибутивные маршруты в ASP.Net Core WebApi

Мне нужно построить проект, который реализует REST API, предопределенный приложением поставщика (которое будет его использовать) - существует около тысячи REST-ресурсов с некоторыми действиями, определенными различными HTTP-глаголами (POST, GET, PUT, DELETE и т. Д.).).

Итак, в идеале, для каждого ресурса у меня должен быть один класс:

public class SomethingController
{
  public Something Post(string name, DateTime time)
  {
     // ...
  }

  public int PostStrange(string text)
  {
     // ...
  }

  public Something Put([FromBody]Something item)
  {
     // ...
  }

  public void Delete(int id)
  {
     // ...
  }
}

В предыдущих версиях я мог просто вызывать MapHttpRoute при регистрации маршрутов, наследовать классы, как это от ApiController - и ASP.NET Web Api будет делать так, как мне нужно... Но в.NET Core я не могу найти ничего подобного MapHttpRoute/ApiController.. Теперь есть атрибуты маршрутизации и http-глагола, и мне нужно явно определить все для каждый класс / метод:

[Route("api/[controller]")]
public class SomethingController : Controller
{
    [HttpPost]
    public Something Post(string name, DateTime time)
    {
        // ...
    }

    [HttpPost("api/[controller]/strange")]
    public int PostStrange(string text)
    {
        // ...
    }

    [HttpPut]
    public Something Put([FromBody]Something item)
    {
        // ...
    }

    [HttpDelete]
    public void Delete(int id)
    {
        // ...
    }
}

Запись этих атрибутов для каждого из тысяч REST-ресурсов очень скучна и подвержена ошибкам...

Я что-то здесь скучаю? Почему в довольно новом и современном ASP.NET Core такая распространенная и важная вещь, как сборка REST-Api, стала слишком сложной по сравнению со старым ASP.NET?

2 ответа

Решение

Есть пакет nuget Microsoft.AspNetCore.Mvc.WebApiCompatShim основная цель которого - облегчить переход с веб-API на ядро. Он также предоставляет способ выполнения конвенциональной маршрутизации к нужным вам действиям. Итак, сначала установите этот пакет, затем при запуске:

public void ConfigureServices(IServiceCollection services) {
    // add conventions here
    services.AddMvc().AddWebApiConventions();                
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env) {
    app.UseMvc(routes => {
        // map one global route
        routes.MapWebApiRoute("WebApi", "api/{controller}");
    });
}

После этой небольшой конфигурации вы можете наследовать ваши контроллеры либо от ApiController, который добавлен в пакет выше для удобства миграции с web api или нативного ядра asp.net Controller, Пример ApiController:

public class SomeController : ApiController {
    // maps to GET /api/Some
    // note - no routing attributes anywhere
    public HttpResponseMessage Get() {
        return new HttpResponseMessage(HttpStatusCode.OK);
    }

    // maps to POST /api/Some
    public HttpResponseMessage Post() {
        return new HttpResponseMessage(HttpStatusCode.OK);
    }
}

Родной контроллер ядра asp.net:

// mark with these attributes for it to work
[UseWebApiRoutes]
[UseWebApiActionConventions]
public class TestController : Controller {
    // maps to GET /api/Test
    // no routing attributes, but two "conventions" attributes
    public IActionResult Get(string p) {
        return new ObjectResult(new { Test = p });
    }
}

Вы также можете пометить свой базовый контроллер следующими атрибутами:

[UseWebApiRoutes]
[UseWebApiActionConventions]    
public class BaseController : Controller {

}

public class TestController : BaseController {
    // maps to GET /api/Test
    // no attributes
    public IActionResult Get(string p) {
        return new ObjectResult(new { Test = p });
    }
}

Если вы не переходите с веб-API - я бы предложил использовать нативный Controller, ApiController имеет другую структуру (аналогичную веб-интерфейсу asp.net ApiController), поэтому нет особых оснований использовать его для чего-либо, кроме своей цели (миграция из веб-интерфейса API).

MapRoute все еще там https://docs.microsoft.com/en-us/aspnet/core/fundamentals/routing

Атрибут маршрутизации MapRouteне заменяет.

По-видимому, есть довольно много примеров, которые опускают часть о маршрутизации, чтобы упростить пример. Так что просто копай ковшом.

Другие вопросы по тегам