Подтвердить что ты не робот

Путаница между Redirect и RedirectToAction

Я изучаю сертификат MS (70-515).
Я смущен тем, что я нашел в Интернете, и тем, что я прочитал на практическом испытании.
Несколько вопросов о состоянии SO, которые используют RedirectToAction, отправляют браузеру 302, что приводит к изменению URL-адреса в адресной строке.

Но это вопрос из 1 практических тестов:

ВОПРОС:

На главном контроллере MVC в настоящее время действует только действие индекса по умолчанию. Соответствующий код показан в следующем примере кода.

public ActionResult Index()
{
    ViewData["Message"] = "Hello!";
    return View();
}

Вам нужно создать действие с именем FindID, которое отображает параметр ID, введенный как часть пути. Если путь не включает параметр ID, ASP.NET должен обработать действие индекса без изменения URL-адреса в адресной строке браузера и не должен генерировать исключение. Какой сегмент кода вы должны использовать?

ИСПРАВЛЯЕМЫЙ ОТВЕТ:

public ActionResult FindID(int? id)
{
    if (!id.HasValue)
        return RedirectToAction("Index");
    ViewData["Message"] = "ID is " + id.ToString();
    return View();
}

ОБЪЯСНЕНИЕ:

Вы можете использовать форму RedirectToAction ActionResult, чтобы заставить MVC обрабатывать другое действие из действия. MVC отказывается от текущего действия и обрабатывает запрос так, как будто маршрут привел непосредственно к действию, к которому вы перенаправляете. По сути, это эквивалентно вызову Server.Transfer в стандартном приложении ASP.NET.

Redirect ActionResult отправляет ответ "HTTP Error 302 - Found" в браузер, что заставляет браузер загружать указанный URL. Это изменяет адрес, который появляется в адресной строке.

Итак:
- Удаляет ли RedirectToAction URL-адрес в браузере нетронутым?
- Изменяет ли перенаправление URL-адрес в браузере?
- Правильно ли объяснение практического теста? Из этого я понимаю, что RedirectToAction НЕ делает 302.

4b9b3361

Ответ 1

Вы можете использовать форму RedirectToAction ActionResult, чтобы заставить MVC обрабатывать другое действие из действия. MVC отказывается от текущего действия и обрабатывает запрос так, как будто маршрут привел непосредственно к действию, к которому вы перенаправляете. По сути, это эквивалентно вызову Server.Transfer в стандартном приложении ASP.NET.

Это неверно.

Оба RedirectToRouteResult (RedirectToAction) и RedirectResult выполняют перенаправление 302, в результате чего URL-адрес в браузере меняется.

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

public ActionResult FindID(int? id)
{
    if (!id.HasValue)
        return View("index");
    ViewData["Message"] = "ID is " + id.ToString();
    return View();
}

Однако я бы не рекомендовал этот подход. Если я делаю запрос mysite.com/products/some-product и some-product не существует, то я должен сообщить об этом пользователю с соответствующим кодом состояния (также важным для поисковых систем).

Если единственная цель вашего действия FindID состоит в том, чтобы что-то сделать с параметром id, то он не должен быть нулевым/необязательным. Таким образом, действие FindID не будет вызываться, если идентификатор не указан.

Ответ 2

Документация для метода RedirectToAction сообщает нам, что он отправляет ответ 302:

"Возвращает ответ HTTP 302 браузеру, что заставляет браузер делать запрос GET на указанное действие."

Изучение кода в dll показывает, что он возвращает объект RedirectToRouteResult, что вызывает перенаправление, поэтому документация верна:

protected internal virtual RedirectToRouteResult RedirectToAction(string actionName, string controllerName, RouteValueDictionary routeValues) {
  RouteValueDictionary routeValueDictionaries;
  if (this.RouteData == null) {
    routeValueDictionaries = RouteValuesHelpers.MergeRouteValues(actionName, controllerName, null, routeValues, true);
  } else {
    routeValueDictionaries = RouteValuesHelpers.MergeRouteValues(actionName, controllerName, this.RouteData.Values, routeValues, true);
  }
  return new RedirectToRouteResult(routeValueDictionaries);
}

Правильным ответом на тестовый вопрос будет использование другого представления:

public ActionResult FindID(int? id) {
  if (!id.HasValue) {
    ViewData["Message"] = "Hello!";
    return View("Index");
  }
  ViewData["Message"] = "ID is " + id.ToString();
  return View();
}

Это будет использовать представление Index вместо представления FindID, которое возвращается бесцельным вызовом View().