Маршрутизація: Поточний запит на дію […] є неоднозначним між наступними методами дій


100

У мене є виклик View Browse.chtml, де користувач може ввести пошуковий термін або залишити пошуковий термін порожнім. Вводячи пошуковий термін, я хочу спрямовувати сторінку, http://localhost:62019/Gallery/Browse/{Searchterm} і коли нічого не вводиться, я хочу спрямовувати браузер на http://localhost:62019/Gallery/Browse/Start/Here.

Коли я намагаюся це, я отримую помилку:

Поточний запит на дію "Огляд" для типу контролера "GalleryController" неоднозначний між такими методами дій: System.Web.Mvc.ActionResult Browse (System.String) типу AutoApp_MVC.Controllers.GalleryController System.Web.Mvc.ActionResult Огляд (Int32, System.String) типу AutoApp_MVC.Controllers.GalleryController

Все, що я роблю з MVC, вперше. Я не впевнений, що ще спробувати в цьому моменті.

public ActionResult Browse(string id)
{
    var summaries = /* search using id as search term */
    return View(summaries);
}

public ActionResult Browse(string name1, string name2)
{
    var summaries = /* default list when nothing entered */
    return View(summaries);
}

У мене це також є на Global.asax.cs:

    routes.MapRoute(
         "StartBrowse",
         "Gallery/Browse/{s1}/{s2}",
         new
         {
             controller = "Gallery",
             action = "Browse",
             s1 = UrlParameter.Optional,
             s2 = UrlParameter.Optional
         });



    routes.MapRoute(
         "ActualBrowse",
         "Gallery/Browse/{searchterm}",
         new
         {
             controller = "Gallery",
             action = "Browse",
             searchterm=UrlParameter.Optional
         });

Відповіді:


161

На контролері ви можете мати максимум 2 методи дії з тим самим іменем, і для цього потрібно 1 [HttpPost], а інший повинен бути [HttpGet].

Оскільки обидва ваші методи GET, вам слід або перейменувати один із методів дії, або перенести його на інший контролер.

Хоча ваші 2 способи перегляду є дійсними перевантаженнями C #, селектор методу дії MVC не може з'ясувати, до якого методу слід звернутися. Він спробує співставити маршрут з методом (або навпаки), і цей алгоритм не набраний сильно.

Ви можете виконати те, що хочете, використовуючи власні маршрути, що вказують на різні методи дій:

... у Global.asax

routes.MapRoute( // this route must be declared first, before the one below it
     "StartBrowse",
     "Gallery/Browse/Start/Here",
     new
     {
         controller = "Gallery",
         action = "StartBrowse",
     });

routes.MapRoute(
     "ActualBrowse",
     "Gallery/Browse/{searchterm}",
     new
     {
         controller = "Gallery",
         action = "Browse",
         searchterm = UrlParameter.Optional
     });

... і в контролері ...

public ActionResult Browse(string id)
{
    var summaries = /* search using id as search term */
    return View(summaries);
}

public ActionResult StartBrowse()
{
    var summaries = /* default list when nothing entered */
    return View(summaries);
}

Ви також можете утримати методи дії, названі однаковими в контролері , застосувавши [ActionName]атрибут до одного, щоб виділити його. Використовуючи той же Global.asax, що і вище, ваш контролер виглядатиме так:

public ActionResult Browse(string id)
{
    var summaries = /* search using id as search term */
    return View(summaries);
}

[ActionName("StartBrowse")]
public ActionResult Browse()
{
    var summaries = /* default list when nothing entered */
    return View(summaries);
}

Отже, мені потрібно буде створити новий погляд у вашому прикладі вище? Схоже, це не допомагає використовувати тег ActionName, оскільки я думаю, що це працює лише для перейменування всіх методів дії (не в змозі зберігати обидва одночасно). Добре знати, як працює MVC. Дякую.
Дейв

6
Ні, вам не потрібно створювати нових переглядів. Ви все одно можете повторно використовувати однаковий вигляд для обох дій. Просто передайте ім'я перегляду як перший аргументreturn View("Browse", summaries);
danludwig

Чи буде перевантаження включена в якийсь майбутній випуск? Модифікація маршрутів - це додаткова робота, і потрібне додаткове обслуговування при внесенні змін.
Old Geezer

@OldGeezer, мабуть, ні, оскільки існує спосіб вирішення (вище), і тому, що перевантажені методи дії в контролері, як правило, не є гарною ідеєю.
danludwig

4

Я не знаю, коли було задано питання, це рішення було доступне, але ви можете використовувати:

Request.QueryString["key"]

Отже, це має добре працювати з вашою проблемою:

[HttpGet]
public ActionResult Browse()
{
    if( Request.QueryString["id"] != null )        
        var summaries = /* search using id as search term */
    else /*assuming you don't have any more option*/
        var summaries = /* default list when nothing entered */

    return View(summaries);
} 

2

Додайте наступний код у RouteConfig.cs перед маршрутом за замовчуванням

routes.MapMvcAttributeRoutes();

І додайте атрибути маршруту в контролер на зразок:

    [Route("Cars/deteals/{id:int}")]
    public ContentResult deteals(int id)
    {
        return Content("<b>Cars ID Is " + id + "</b>");
    }

    [Route("Cars/deteals/{name}")]
    public  ContentResult deteals(string name)
    {
        return Content("<b>Car name Is " + name + "</b>");

    }

1

Я думаю, що суть полягає в тому, що вам не потрібно неявно перевіряти параметри запитів, використовуючи клас запиту.

MVC робить для вас картування (якщо ви не внесли серйозних змін у маршрути MVC).

Таким чином шлях дії

/umbraco/Surface/LoginSurface/Logout?DestinationUrl=/home/

автоматично буде доступний для вашого (поверхневого) контролера із визначеним параметром:

public ActionResult Logout(string DestinationUrl)

MVC виконує роботу.

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