Вопрос по c#, asp.net-mvc – Маршрутизация: текущий запрос на действие […] неоднозначен между следующими методами действия

85

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

Когда я пытаюсь это сделать, я получаю сообщение об ошибке:

The current request for action 'Browse' on controller type 'GalleryController' is ambiguous between the following action methods: System.Web.Mvc.ActionResult Browse(System.String) on type AutoApp_MVC.Controllers.GalleryController System.Web.Mvc.ActionResult Browse(Int32, System.String) on type 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
         });

Ваш Ответ

4   ответа
149

ем же именем, и для этого 1 должен быть[HttpPost], а другой должен быть[HttpGet].

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

Хотя ваши 2 метода Browse являются допустимыми перегрузками 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);
}
Отличный ответ, спасибо tom redfern
Будет ли перегрузка включена в некоторые будущие выпуски? Изменение маршрутов - это дополнительная работа, и при внесении изменений требуется дополнительное обслуживание. Old Geezer
Отлично, спасибо Dave
Итак, мне нужно создать новый вид в вашем примере выше? Похоже, что это не помогает использовать тег ActionName, так как я думаю, что он работает только для переименования всех методов действия (невозможно сохранить оба одновременно). Приятно знать, как работает MVC. Благодарность Dave
Нет, вам не нужно создавать новые представления. Вы все еще можете использовать один и тот же вид для обоих действий. Просто передайте имя представления в качестве первого аргументаreturn View("Browse", summaries); 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);
} 
1

что суть в том, что вам не нужно неявно проверять параметры строки запроса, используя класс запроса.

MVC сделает отображение за вас (если вы не внесли серьезных изменений в ваши маршруты MVC).

Это путь к действующей ссылке

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

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

public ActionResult Logout(string DestinationUrl)

MVC делает работу.

1

Добавьте следующий код в 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>");

    }

Похожие вопросы