Маршрутизация - WebAPI и MVC в одном проекте - PullRequest
0 голосов
/ 31 мая 2019

У меня 2 контроллера.Оба имеют дело с Баром (потомком Foo).

Один из них предназначен для MVC, который возвращает представления.

[Route("Foo/Bar")]
public class FooBarController : ControllerBase
{
    public IActionResult Index()
    {
        // ...
    }

    public IActionResult SomeAction()
    {
        // ...
    }
}

Один из них предназначен для API, который существует под папка"api".

[Route("api/Foo/Bar")]
[ApiController]
public class FooBarAPIController : ControllerBase
{
    //
}

Не добавляя следующую строку в класс FooBarController, я могу получить доступ к контроллеру API (например: / api / foo / bar / {id})и контроллер MVC (например: / FooBar / SomeAction)

[Route ("Foo / Bar")]

Но когда я это делаю, маршрутизация нарушаетсяи я получаю следующую ошибку при попытке доступа к / Foo / Bar / SomeAction

AmbiguousMatchException: запрос соответствует нескольким конечным точкам.Совпадения:

Controllers.MVC.FooBarController.Index

Controllers.MVC.FooBarController.SomeAction

Ответы [ 4 ]

1 голос
/ 31 мая 2019

Для вашего контроллера API, я рекомендую изменить Route на RoutePrefix["api"], таким образом, все ваши методы API будут содержать только маршрут (возможно, имя, отличное от того, которое вы используете для своего Home Controller.

[RoutePrefix("api")]
public class MyApiController : ApiController 
{
    [HttpGet, Route("foo/bar")]
    public IHttpActionResult GetSomething()
    {
        //do something when routing to /api/foo/bar
    }

    [HttpPost, Route("foobar/foobar")]
    public IHttpActionResult GetSomething()
    {
        //do something when routing to /api/foobar/foobar
    }
}

Тот же совет относится к вашему HomeController (если вы действительно хотите добавить к нему маршрут, и каждый метод в этом классе будет маршрутизироваться в соответствии с именем их метода, например. Index)

[RoutePrefix("foo/bar")]
public class MyController : BaseController
{
    public IActionResult Index()
    {
        return View(); //or something
    }

    public IHttpActionResult Contact()
    {
        return View(); //or something
    }
}
1 голос
/ 03 июня 2019

Если вы хотите направить FooBarController.SomeAction с /Foo/Bar/SomeAction, вы можете попробовать что-то вроде

    [Route("Foo/Bar/[action]")]
    public class FooBarController : ControllerBase
    {
            public IActionResult Index()
            {
                    // ...
            }

            public IActionResult SomeAction()
            {
                    // ...
            }
    }
1 голос
/ 31 мая 2019

Если атрибут не применен, FooBarController использует обычную маршрутизацию, которая, вероятно, уже используется по умолчанию.Обычно он имеет индекс в качестве действия по умолчанию и позволяет также указать имя действия, поэтому все работает.

Когда вы применяете атрибут, все действия в этом контроллере теперь используют маршрутизацию атрибута.Эти два типа маршрутизации не объединены, вы можете использовать только один или другой.Обратите внимание, что

"При маршрутизации атрибута имя контроллера и имена действий не играют роли, в которой выбирается действие."

( источник документов ),Таким образом, эти два действия становятся одинаковыми, их имена игнорируются, и невозможно определить, какое из них использовать.Поэтому вам нужно помочь:

[Route("Foo/Bar")]
public class FooBarController : ControllerBase
{
    [Route("")]      // To make it default for "Foo/Bar"
    [Route("Index")] // Combines to define the route template "Foo/Bar/Index"
    public IActionResult Index()
    {
        // ...
    }

    [Route("SomeAction")] // Combines to define the route template "Foo/Bar/SomeAction"
    public IActionResult SomeAction()
    {
        // ...
    }
}

Да, это более многословно.Из того же источника:

Для маршрутизации атрибутов требуется больше ввода для указания маршрута;стандартный маршрут по умолчанию обрабатывает маршруты более кратко.Однако маршрутизация атрибутов позволяет (и требует) точного контроля того, какие шаблоны маршрутов применяются к каждому действию.

0 голосов
/ 03 июня 2019

Мне удалось заставить его работать, используя следующее.

[Route("Foo/Bar")]
[Route("Foo/Bar/[action]")]
public class FooBarController : Controller
{
    [HttpGet("")]
    public IActionResult Index()
    {
        return RedirectToAction("SomeAction");
    }

    public IActionResult SomeAction()
    {
        return View();
    }

}
...