I can easily reproduce this issue in Alloy template.
If you use Html.BeginForm in the page, the form's action url is correct. However if it is inside another view and render using Html.Render, the form's action url is not parsed by route.
The child action request (caused by @Html.Action) will not go through "ordinary" routing, instead ASP.NET MVC will route the request directly to the controller. This means that values set on RouteData by EPiServer routing will not be present on child actions.
More specifically in this case the "node" parameter (that indicates which content item the request is for) is missing.
What you can do is add the following to your partial view:
@using (Html.BeginForm("ExternalLogin", "LoginPage", new { ReturnUrl = ViewBag.ReturnUrl, node = ViewContext.RequestContext.GetContentLink() }))
{
.....
}
Hi Johan
Thanks for taking a look of my issue. The solution you provide did partially solve my problem. The url was generated correctly if the partial view resides in the LoginPage view.
However I had another partial login area sitting on the layout page, it contains two links to link to "login" and "join" page, these two links's action are inside the "LoginPageController", when I used the same technique with Url.Action, it still generated /LoginPage/Index and /LoginPage/Join.
I get a bit frustrated of the episerver routing system.
Johan
Can you point me out how to make the Url.Action work in my situtation?
Cheers
The reason it does not work is that in the CMS Route it will not try to resolve a VirtualPath if the controller in the route values differs from the controller for the main request. I have reported a bug for that either we should always try to resolve the virtual path or that it should be possible to control the behaviour by a parameter in route values.
But for now you can do a workaround by setting the controller on the main request temporary to the same as the sub controller, like:
@{
var currentController = Html.ViewContext.RouteData.Values[RoutingConstants.ControllerKey];
Html.ViewContext.RouteData.Values[RoutingConstants.ControllerKey] = "Login";
@Url.Action("ExternalLogin", "Login", new { node = new ContentReference(17) });
Html.ViewContext.RouteData.Values[RoutingConstants.ControllerKey] = currentController;
}
Ps.
new ContentReference(17) should be replaced with the reference to your login page.
Hi
I am having some trouble with EPiServer default route. I have a login page type in the CMS and a corresponding controller to serve the login page.
Below is my view, the view contains two post forms, first form is rendered from controller directly, post form action just works fine. However the second form is rendered inside another view by using Html.Action, the post form action is completed wrong and also there is no trailing splash append after the action which cause route not match the incoming request.
e.g. the first form use the following code snippet
the form action is rendered as "/signin/auth/?ReturnUrl= (My login page name url in CMS is called signin, so I guess that's why when I Passed LoginPageController to the form, it is rendered as my real page name)
the second form use the Html.Action to render the partial view, the action is rendered as "/LoginPage/ExternalLogin?ReturnUrl=" (see here, there is no trailing slash and the controller name is translated to page name - signin like the first form)
The ExternalLoginsList returns the following view
I am so confused about the inconsistent behaviour, can someone explain this to me?