We have a login/register modal that is being called via javascript on the front end. I created a custom route to point to the right action controller, and it works fine in every environment - except when we try with https. So, http://website.com/account/login works, but https://website.com/account/login throws the following error:
Exception type: InvalidOperationException Exception message: Attempt to retrieve context object of type 'Sitecore.Mvc.Presentation.RenderingContext' from empty stack.
The line that this error hits on is this (first line in the login controller):
var datasource = SitecoreContext.GetItem<LoginForm>(RenderingContext.Current.Rendering.DataSource);
Here's the custom routing in RegisterRoutes.cs:
RouteTable.Routes.MapRoute("AccountLogin", "Account/Login",
new { controller = "Account", action = "Login" });
Using Sitecore 8.1 rev. 160302.
Edit: I should additionally note that this error is happening only after the user submits login information, but that the line this is hitting is not in the HttpPost version of the controller, which makes this mystery extra puzzling!
Order of operations:
- Page hits the login controller (non httppost version) and loads the login view with no issues
- Javascript triggers the modal popup and user fills out login information and clicks the submit button
- 500 error is thrown and returned to the javascript from the non httppost version of the login controller. (I cannot tell at this point if httppost is also getting hit.)
Additonal Edit: Adding javascript and controller action result methods.
Javascript
$.ajax({
url: $form.attr('action'),
type: 'post',
dataType: 'json',
data: $form.serialize()
})
.done(function (data) {
console.log("data");
console.log(data);
clearInterval(spinner);
$self.find(".spinner").hide();
$(".login-subscribe .tabs .tab:not(.selected) a").removeClass("disabled");
if ($.isEmptyObject(data)) {
window.location.reload();
return;
}
if (typeof data !== 'undefined') {
if ('userRef' in data) {
$('.modal-overlay').hide();
//success - do stuff
}
if ('errorMsg' in data) {
$self.prop("disabled", false)
.parent()
.find("input[required]")
.addClass("error")
.end()
.find(".errorMsg")
.html(data.errorMsg)
.show();
}
}
})
.fail(function (error) {
console.log("fail");
console.log(error);
$self.parent()
.find("input[required]")
.addClass("error")
.end()
.find(".errorMsg")
.show();
});
Controller action result methods:
public ActionResult Login()
{
var datasource = SitecoreContext.GetItem<LoginForm>(RenderingContext.Current.Rendering.DataSource);
if (datasource == null)
{
return DataSourceNotConfiguredResult;
}
LogInViewModel logInViewModel = new LogInViewModel(datasource);
return View(Views.LogIn, logInViewModel);
}
[HttpPost]
public ActionResult Login(string Email, string Password, string RememberMe)
{
if (!string.IsNullOrWhiteSpace(Email) && !string.IsNullOrWhiteSpace(Password) &&
!string.IsNullOrWhiteSpace(RememberMe))
{
bool rememberMe = false;
if (RememberMe.ToLower() == "true")
{
rememberMe = true;
}
Tuple<AccountResultCode, string> loginResult = userAccountUtilities.Login(Email, Password, rememberMe);
if (loginResult.Item1 == AccountResultCode.Success)
{
if (string.IsNullOrWhiteSpace(loginResult.Item2))
{
return Content("{}", "application/json");
}
return Content(loginResult.Item2, "application/json");
}
else
{
string errorMsg = ErrorMessaging(loginResult.Item1);
errorMsg = "{\"errorMsg\": \"" + errorMsg.Replace("\n", "").Replace("\"", "\\\"") + "\"}";
return Content(errorMsg, "application/json");
}
}
return Content("");
}