Try our conversational search powered by Generative AI!

Problems with currentPage MVC

Vote:
 

I'm having some issues with EPiServer/MVC where my currentPage gets null.
What I'm trying to do is redirect from a ProfileBlock that shows a little information from the Profile of the user, which is located in a ContentArea on the StartPage, to a full ProfilePage with all information about the user, where the user also can edit his/her own information.

But the currentPage is null because I'm trying to retrieve a ProfilePage, but I'm redirected from a ProfileBlock on the StartPage so it always ends up as null.
Is there any good way or 'proper' way of doing this?

Here's my blockcontroller:


public class ProfileBlockController : BlockController
    {
        public override ActionResult Index(ProfileBlock currentBlock)
        {
            ProfileBlockViewModel model;
            if (currentBlock != null)
            {
                model = new ProfileBlockViewModel(currentBlock);
            }
            else
            {
                model = (ProfileBlockViewModel)Session["model"];
            }
            model.CurrentUser = ConnectionHelper.GetCurrentUserByEmail(User.Identity.Name);
            var availableStatuses = ConnectionHelper.GetAllOfficeStatuses();
            availableStatuses.Remove(model.CurrentUser.OfficeStatus);
            model.AvailableStatusChanges = availableStatuses;
            Session["model"] = model;

            return PartialView(model);
        }

        [HttpPost]
        public ActionResult ChangeOfficeStatus(int statusID)
        {
            var model = (ProfileBlockViewModel)Session["model"];
            ConnectionHelper.ChangeOfficeStatus(statusID, model.CurrentUser.UserID);
            return RedirectToAction("Index", model);
        }

        [HttpPost]
        public ActionResult ChangeTemporaryMessage(string TemporaryMessage)
        {
            var model = (ProfileBlockViewModel)Session["model"];
            ConnectionHelper.ChangeTemporaryMessage(TemporaryMessage, model.CurrentUser.UserID);
            return RedirectToAction("Index", model);
        }

        [HttpPost]
        public ActionResult ChangeContactInformation(string ContactInformation)
        {
            var model = (ProfileBlockViewModel)Session["model"];
            ConnectionHelper.ChangeContactInformation(ContactInformation, model.CurrentUser.UserID);
            return RedirectToAction("Index", model);
        }



And in this block if the user doesn't have an image, this link will be shown:

@using (Html.BeginForm("EditProfile", "ProfilePage", FormMethod.Post))
{
          
}


And when you click it you enter the controller for the ProfilePage:


    public class ProfilePageController : PageController
    {
        public ActionResult Index(ProfilePage currentPage)
        {
            ProfilePageViewModel model = new ProfilePageViewModel(currentPage);
            model.currentUser = ConnectionHelper.GetCurrentUserByEmail(User.Identity.Name);
            return View(model);    
        }

        public ActionResult EditProfile(ProfilePage currentPage) //This is where the currentPage is null
        {
            if (currentPage == null)
            {
             //Any possible solution here?
            }
            ProfilePageViewModel model = new ProfilePageViewModel(currentPage);
            model.currentUser = ConnectionHelper.GetCurrentUserByEmail(User.Identity.Name);
            return View(model);  
        }

        public ActionResult SaveChanges(ProfilePage currentPage)
        {
            return View();
        }
    }




Any ideas?

Regards
Ludvig Flemmich

#113043
Nov 11, 2014 15:11
Vote:
 

Have you tried adding the [HttpPost] attribute to your EditProfile method ?

#113103
Nov 13, 2014 9:59
Vote:
 

Yes I've tried that already :/
The thing is that I recently found an almost identical MVC setting which works.
The controller inherits the same data in both controllers of the same PageType, the routing matches and the post is also the same, but one of them works while the other one doesn't get currentPage values.

Here's a link to my StackOverflow post about the same issue, I'll add more extensive code here aswell.


Working controller:

namespace BlocketProject.Controllers
{
    public class ProfilePageController : PageController<ProfilePage>
    {
        public ActionResult EditProfile(ProfilePage currentPage)
        {
            var model = new ProfilePageViewModel(currentPage);
            model.CurrentUser = ConnectionHelper.GetUserInformationByEmail(User.Identity.Name);
            return View("EditProfile", model);
        }
    }
}


"Broken" controller:

namespace Intranet.Controllers
{
    public class ProfilePageController : PageController<ProfilePage>
    {
        public ActionResult EditProfile(ProfilePage currentPage)
        {
            ProfilePageViewModel model = new ProfilePageViewModel(currentPage);
            model.currentUser = ConnectionHelper.GetCurrentUserByEmail(User.Identity.Name);
            return View("EditProfile", model);
        }
    }
}

Working form(posted from _Layout file):

@using (Html.BeginForm("EditProfile", "ProfilePage", FormMethod.Post))
{
  <li>
       <button type="submit" class="dropdownButton">
             Redigera Profil
       </button>
  </li>
}

"Broken" form(posted from a block, but also tried from other pages and _Layout):

@using (Html.BeginForm("EditProfile", "ProfilePage", FormMethod.Post))
{
    <button type="submit">Redigera profil</button>
}



Both have the following MVC routing:

using System;
using System.Web.Mvc;
using System.Web.Routing;

namespace Intranet
{
    public class EPiServerApplication : EPiServer.Global
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
        }
        protected override void RegisterRoutes(RouteCollection routes)
        {
            base.RegisterRoutes(routes);
            routes.MapRoute(
              "Default",                                             
              "{controller}/{action}/{id}",                           
              new { controller = "Home", action = "Index", id = "" });
        }
    }
}


And I'm all out of ideas of what could be causing this.

#113130
Edited, Nov 13, 2014 14:37
Vote:
 

ModelBinding for parameter "currentPage" requires that the request has been routed through a EPiServer route (serving urls like http://mysite/some/cms/structure/page) and will not work for standard MVC routed request like http://mysite/home/edit, where home is home controller and edit an action on home controller). 

So could it be that the request controller that have currentPage is requested through an ordinary MVC route?

#113136
Nov 13, 2014 18:05
Vote:
 

Maybe, but I find it weird because they are coded the same way and both work towards the url 'ProfilePage/EditProfile', and one of them works while the other one doesn't.
And I cannot exactly see what happens inbetween the post and the retrieval of the currentPage in the controller, which is why it is so hard to locate the problem.

Do you have any suggestions of where I can look for the problem?

#113185
Nov 14, 2014 12:28
Vote:
 

Bump

#113392
Nov 19, 2014 15:32
Vote:
 

When you in ProfileBlockController do a RedirectToAction("Index", model), it will always jump back to the Index method of ProfileBlockController. If you want to redirect to another controller (which seems to be what you want to do), you need to supply the routeValues argument to, indicating which controller you're aiming at.

Also, consider what Johan said earlier. If you're executing ProfilePage/EditProfile, you're essentialy using the default route that you've configured, and this is executed outside Episerver context. CurrentPage will always be null in such a route.

If you want to redirect to an episerver page you need to resolve the URL to that page, see http://stackoverflow.com/questions/22327056/redirect-to-another-any-episerver-page-from-mvc-controller

#113414
Nov 19, 2014 19:16
Vote:
 

In this specific scenario I would just add a PageReference property to the start page and browse the profile page (you have one in the site's page tree right?) and use a standard link to the EditProfile action on the profile page. As far as I can see, no form post is required here?

On your start page model:

public virtual PageReference ProfilePageLink { get; set; }

On your block view model:

public PageReference ProfilePageLink { get; set; } // You need to set this property in your block controller by fetching start page and get the value of the property.

And in your block view, if the user doesn't have an image:

<a href="@Url.ContentActionUrl(Model.ProfilePageLink, "EditProfile")">@Model.CurrentUser.FirstName @Model.CurrentUser.LastName har ingen profilbild. Klicka här för att lägga till en.</a>

Url.ContentActionUrl is a custom extension method:

public static string ContentActionUrl(this UrlHelper urlHelper, ContentReference contentLink, string actionName)
{
    var actionUrl = new UrlBuilder(urlHelper.ContentUrl(contentLink));
    actionUrl.Path = VirtualPathUtility.AppendTrailingSlash(actionUrl.Path) + actionName;
    return actionUrl.ToString();
}

 

#113778
Nov 27, 2014 15:57
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.