Nie działa RedirectToAction

0

W momencie próby wykonania redirectu w akcji AddToCart w CartController w ogóle nie wchodzi do Index, nie ma też żadnej informacji o błędzie. Ma ktoś może pomysł, dlaczego to nie działa?

	    public ActionResult Index()
        {
            var cartItems = _shoppingCartManager.GetCart();
            var cartTotalPrice = _shoppingCartManager.GetCartTotalPrice();

            CartViewModel cartVM = new CartViewModel() { CartItems = cartItems, TotalPrice = cartTotalPrice };

            return View(cartVM);
        }

        public ActionResult AddToCart(int id)
        {
            _shoppingCartManager.AddToCart(id);

            return RedirectToAction("Index");
        }

Wcześniej akcja wywoływana jest z poziomu widoku w taki sposób:

<a class="addtocartlink" href="@Url.Action("AddToCart", "Cart", new { id = newEbook.EbookId, ebookName = HelperMethods.RemoveDiacritics(newEbook.EbookTitle) })">
2

Podejrzewam, że nie przebudowałeś kodu. Przejdź po kodzie debugerem i zobacz, czy faktycznie wywołują się te akcje, które powinny. Zobacz też w dev toolsach (F12) w zakładce Network, czy do przeglądarki przyszedł status http 301 albo 302 (może to wymagać włączenia w narzędziu opcji "preserve log").

BTW masz AddToCart(int id), ale wywołujesz AddToCart(id, ebookName) - nie masz aby przeciążonej wersji tej metody?

0

Kod jest przebudowany, poprawiłem też akcję i teraz jest przekazywana tylko na podstawie Id. Jak wchodziło do niej wcześniej, tak wchodzi cały czas, jednak niestety nadal nie wykonuje się redirect. Pojawia się następująca informacja o błędzie po stronie przeglądarki. Dziwne tym bardziej, że plik "~/Views/Cart/Index.cshtml" istnieje. Status http to 302.

Błąd źródła: 

Podczas wykonywania bieżącego żądania sieci Web został wygenerowany nieobsługiwany wyjątek. Informacje dotyczące pochodzenia i lokalizacji wyjątku można zidentyfikować przy użyciu poniższego śladu stosu wyjątku.

Ślad stosu: 

[InvalidOperationException: The view 'Cart' or its master was not found or no view engine supports the searched locations. The following locations were searched:
~/Views/Home/Cart.aspx
~/Views/Home/Cart.ascx
~/Views/Shared/Cart.aspx
~/Views/Shared/Cart.ascx
~/Views/Home/Cart.cshtml
~/Views/Home/Cart.vbhtml
~/Views/Shared/Cart.cshtml
~/Views/Shared/Cart.vbhtml
~/__MVCSITEMAPPROVIDER/Cart.ascx]
   System.Web.Mvc.ViewResult.FindView(ControllerContext context) +382
   System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context) +116
   System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult) +13
   System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +56
   System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +420
   System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult) +52
   System.Web.Mvc.Async.<>c__DisplayClass2b.<BeginInvokeAction>b__1c() +173
   System.Web.Mvc.Async.<>c__DisplayClass21.<BeginInvokeAction>b__1e(IAsyncResult asyncResult) +100
   System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +10
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) +27
   System.Web.Mvc.Controller.<BeginExecuteCore>b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState) +13
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +29
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
   System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +36
   System.Web.Mvc.Controller.<BeginExecute>b__15(IAsyncResult asyncResult, Controller controller) +12
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +22
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
   System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +26
   System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult) +10
   System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__5(IAsyncResult asyncResult, ProcessRequestState innerState) +21
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +29
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
   System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +28
   System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9
   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +9748493
   System.Web.HttpApplication.ExecuteStepImpl(IExecutionStep step) +48
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +159
0

Tylko zwróć uwagę, że aplikacja nie szuka widoku w ~/Views/Cart/Index.cshtml

0

Sprawdź debuggerem czy wchodzi czy nie. Jeżeli nie to pokaż cały kod kontrolera.

0

Debuggerem wchodzi. Kod jest taki:


namespace EbookApp.Controllers
{
    public class CartController : Controller
    {
        // GET: Cart

        private StoreContext _db;

        private ISessionManager _sessionManager;

        private readonly IShoppingCartManager _shoppingCartManager;

        public CartController()
        {
            
        }

        public CartController(StoreContext db, ISessionManager sessionManager, IShoppingCartManager shoppingCartManager)
        {
            _db = db;
            _sessionManager = sessionManager;
            _shoppingCartManager = shoppingCartManager;
        }

        public ActionResult Index()
        {
            var cartItems = _shoppingCartManager.GetCart();
            var cartTotalPrice = _shoppingCartManager.GetCartTotalPrice();

            CartViewModel cartVM = new CartViewModel() { CartItems = cartItems, TotalPrice = cartTotalPrice };

            return View(cartVM);
        }

        public ActionResult AddToCart(int id)
        {
            _shoppingCartManager.AddToCart(id);

            return RedirectToAction("Index");
        }

        public int GetCartItemsCount()
        {
            return _shoppingCartManager.GetCartItemsCount();
        }
    }
}
0

A spróbuj co się stanie jak zrobisz tak:

return RedirectToAction("Cart", "Index");
0

Refresh. Jak ktoś ma jakiś pomysł, jak sobie poradzić z tym dziwnym problemem, prosiłbym o pomoc. Niemal pewny jestem, że problem nie stoi po stronie poprawności kodu.

0
  1. Czy jak zrobisz
return RedirectToAction("Cart", "Index");

to szuka wtedy właściwego widoku?

  1. Pokaż ustawienia routingu.
0
  1. Właściwie odwrotnie, czyli
return RedirectToAction("Index", "Cart");

Jak napisałem, wtedy do widoku nie wchodzi. Ale jeśli w przeglądarce wpiszemy localhost/Cart/Index, znajduje ten widok, produkt też dodany jest poprawnie. Natomiast z akcji AddToCart następuje próba wywołania localhost/Cart, co nie zwraca żadnego rezultatu.

  1. Config jest taki:
namespace OkoNaSwiat
{
    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                name: "ProductDetails",
                url: "ebook-{ebookName}-{id}",
                defaults: new { controller = "Store", action = "Details" }
            );

            routes.MapRoute(
                name: "StaticPages",
                url: "{viewName}",
                defaults: new { controller = "Home", action = "StaticContent" }
            );

            routes.MapRoute(
                name: "ProductList",
                url: "kategorie/{categoryName}",
                defaults: new { controller = "Store", action = "List" }//,
                //constraints: new { categoryName = @"[\w& ]+" }
            );

            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );
        }
    }
}

Powinno na podstawie ostatniego ustawienia wejść do localhost/Cart/Index, natomiast na podstawie kodu:

[InvalidOperationException: The view 'Cart' or its master was not found or no view engine supports the searched locations. The following locations were searched:
~/Views/Home/Cart.aspx
~/Views/Home/Cart.ascx
~/Views/Shared/Cart.aspx
~/Views/Shared/Cart.ascx
~/Views/Home/Cart.cshtml
~/Views/Home/Cart.vbhtml
~/Views/Shared/Cart.cshtml
~/Views/Shared/Cart.vbhtml
~/__MVCSITEMAPPROVIDER/Cart.ascx]

ewidentnie widać, że szuka tego wszędzie, tylko nie tam, gdzie trzeba, jeszcze szukając Cart.cshtml w miejsce Index.cshtml.

2

Fajny przypadek :), problem jest w tym że RedirectToAction zjada parametr "action" jeśli jest taki sam jak domyślny.
Czyli z "Cart/Index" zostaje nam samo "Cart", a to jest wyłapywane przez Twoja drugą drogę "StaticPages" czyli sterowanie trafia do kontrolera "Home" i akcji StaticContent.

Najprostsze rozwiązanie to
Redirect("/Cart/Index"); zamiast RedirectToAction("Cart", "Index");
a najlepiej to by było poprawić drogi, tak żeby ze sobą nie kolidowały :)

0

Dokładnie to było problemem:) Dzięki wielkie za pomoc. Jeszcze odośnie samego mechanizmu routingu: rozumiem, że najpierw trafia do niego adres url, a potem na jego podstawie ma zostać wybrana konkretna akcja danego kontrolera i zwrócony widok dla podanego adresu?

1 użytkowników online, w tym zalogowanych: 0, gości: 1