Понимание маршрутизации ASP.NET MVC 5

Я знаю, что здесь много вопросов и ответов относительно маршрутизации MVC. К сожалению, у меня все еще возникают проблемы с маршрутизацией, которых я не понимаю.

Прежде всего - могу ли я иметь перегруженные ActionResults в моем контроллере?

Например, я делаю 3 запроса к одному и тому же контроллеру / действию с разными параметрами.

  • "/ MyController / DoSomething"
  • "/ MyController / DoSomething / [Guid String]
  • "/ MyController / DoSomething / [Guid String] / TypeA

... а в контроллере у меня есть эти методы

public ActionResult DoSomething()
{
    ViewBag.Title = "Do Something By Default";
    return View();
}

public ActionResult DoSomething(String id)
{
    ViewBag.Title = "Do Something By id";
    return View();
}

public ActionResult DoSomething(String id, String type)
{
    ViewBag.Title = "Do Something By id and type";
    return View();
}

Я ожидал, что каждый перегруженный метод будет делать это, но это не так. Единственный вызываемый ActionMethod - это DoSomething () независимо от вводимых мной параметров. Короче говоря, DoSomething (String id) и DoSomething (String id, String type) полностью игнорируются.

Даже когда я пытался это сделать ...

public ActionResult DoSomething(String? id)
{
     ViewBag.Title = "Do Something Conditionally";
     return View();
}

... просто чтобы посмотреть, что произойдет. Выдается ошибка компиляции

Ошибка 4 Тип 'string' должен быть типом значения, не допускающим значения NULL, чтобы использовать его в качестве параметра 'T' в универсальном типе или методе 'System.Nullable'

ПРИМЕЧАНИЕ. Мои параметры - это строки (технически GUID), а не целые числа.

Я подумал, что, возможно, мне нужно сопоставить эти маршруты в классе / App_Start / RouteConfig, и попробовал это, чтобы посмотреть, смогу ли я заставить работать один перегруженный метод.

routes.MapRoute(
   "MyController",
   "MyController/DoSomething/{id}",
   new { controller = "MyController", action = "DoSomething", id = "" }
);

... и все же DoSomething (String id) ActionResult не был вызван. Ни ошибок, ни исключений. Было бы, если бы у меня даже не было указанного MapRoute.

Что-то мне здесь не хватает? Будем очень признательны за любые идеи, инструкции и рекомендации, которые вы можете предоставить.


person Sean Mc    schedule 06.02.2015    source источник
comment
Нет, маршрутизация не работает. Вы можете добиться того, чего хотите, но это немного сложнее и требует использования ограничений маршрутизации и других факторов. У меня сейчас нет времени объяснять это, но, надеюсь, другие сделают это. MVC допускает только один метод действия для каждой HTTP-команды (get, post и т. Д.) Для любого заданного метода. Таким образом, вы можете иметь Index () и Index (строка x), но они должны быть разными командами. Это ограничение механизма привязки модели. MVC не знает, какую перегрузку выбрать, потому что нет типов, связанных с полями формы HTTP или строками запроса.   -  person Erik Funkenbusch    schedule 06.02.2015
comment
Что ж - я думаю, это решает. Спасибо, Эрик - я ценю вашу проницательность. Я изучу ограничения маршрутизации, чтобы узнать, смогу ли я обойти это.   -  person Sean Mc    schedule 06.02.2015
comment
Хорошо, что ж, я смог заставить работать определенные аспекты, которые, безусловно, помогут. Оказывается, у меня есть ActionResult с параметром, например: DoSomething (String id), и у меня нет метода DoSomething () ActionResult - я могу использовать этот метод с параметром или без него условно. Я тестировал его только со строками, но он работает. Этого, безусловно, будет достаточно для использования одного и того же действия и представления для новых форм для вставок и предварительно заполненных форм для обновлений.   -  person Sean Mc    schedule 06.02.2015
comment
Отдельно стоит отметить, что причина, по которой String? недействительна, заключается в том, что String является ссылочным типом - он уже допускает значение NULL. Вы можете заключать в объект Nullable<> только типы значений, потому что они не могут содержать null сами по себе.   -  person Blindy    schedule 06.02.2015


Ответы (1)


Для эффективного выполнения этого все, что требуется, - это определить, с какими параметрами вы работаете, и применить значения по умолчанию в случае, если параметры равны нулю. В конечном итоге это приведет к единственному действию. В случае приведенного выше примера - удаление DoSomething () и DoSomething (String id) и работа только в пределах DoSomething (String id, String type)

Пример

public ActionResult DoSomething(String id, String type)
{
    var _id = String.Empty
    var _type = String.Empty

    if(id != null)
    {
        _id = id
    }

    if(type != null)
    {
       _type = type
    }

    ViewBag.Title = "Do Something By id and type conditionally";
    return View();
}

При выполнении следующих запросов все они будут работать в соответствии с логическими условиями в рамках одного действия.

  • "/ MyController / DoSomething"
  • "/ MyController / DoSomething / [Guid String]
  • "/ MyController / DoSomething / [Guid String] / TypeA
person Sean Mc    schedule 06.02.2015
comment
Да, это прекрасный способ справиться с этим. type будет иметь значение null, если параметр не указан (при условии, что вы сделаете параметр необязательным в своем маршруте). Хотя у вас не может быть типа, если у вас нет идентификатора ... поэтому не уверен, является ли это требованием. - person Erik Funkenbusch; 06.02.2015