Reputation: 2616
In my main layout I'm trying to add a login partial view via ajax, however I keep getting 'Internal Server Error'. I've tried various other posted solutions without luck
Everything is pretty standard I've got my HomeController and index.cshtml (which uses layout.cshtml)
In the layout, once the document is ready, I use ajax to see if a user is logged in via the HomeController, if the returned value is false I want to show a partial view.
The function showLoginPartial where it trys, via ajax, to get the partial view from the LoginController fails
"Error in showLoginPartial(): Internal Server Error :-: error"
What am I doing wrong?
HomeController method:
public JsonResult IsUserLoggedIn()
{
return Json(new { result = (CurrentUser != null) }, JsonRequestBehavior.AllowGet);
}
layout jquery:
$(document).ready(function () {
checkLoggedIn();
function checkLoggedIn() {
$.ajax({
url: '@Url.Action("IsUserLoggedIn", "Home", new { })',
success: function (data) {
if (data.result == false) {
//Show the login partial view
showLoginPartial();
}
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert("Error in checkLoggedIn(): " + errorThrown + " :-: " + textStatus);
}
});
}
function showLoginPartial() {
$.ajax({
url: '@Url.Action("LoginDisplay", "Login", new { })',
success: function (response) {
//add the partial view after #ib-container div
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
//Error displays
alert("Error in showLoginPartial(): " + errorThrown + " :-: " + textStatus);
}
});
}
})
LoginController:
public class LoginController : Controller
{
// GET: Login
[ChildActionOnly]
public ActionResult LoginDisplay()
{
return PartialView("_LoginDisplay");
}
public JsonResult UserLoggedOut()
{
return Json(new { result = Nuclei.Models.CurrentUserAccount.Instance.LoggedOut }, JsonRequestBehavior.AllowGet);
}
public JsonResult UserAutoAuthenticate()
{
bool l_result = false;
System.Threading.Thread.Sleep(3000);
return Json(new { result = l_result }, JsonRequestBehavior.AllowGet);
}
public JsonResult UserManualAuthenticate()
{
bool l_result = false;
System.Threading.Thread.Sleep(3000);
return Json(new { result = l_result }, JsonRequestBehavior.AllowGet);
}
public JsonResult SendUserCredentials()
{
bool l_result = true;
System.Threading.Thread.Sleep(3000);
return Json(new { result = l_result }, JsonRequestBehavior.AllowGet);
}
}
[EDIT]
Just tried adding the partial view via an RenderAction() and it worked, but this is not what I'm after, definitely want to use ajax.
@{ Html.RenderAction("LoginDisplay", "Login"); }
Added the rest of the methods into the LoginController above as well
_LoginDisplay.cshtml
<div id="login_layer_overlay">
</div>
<div id="login_layer">
<div id="MainLoginDiv">
<div id="LoginHeaderDiv" class="text-center">
<h3 id="LoginHeader" class="page-header" style="color:white;"> </h3>
</div>
<div id="Spinner" class="spinner">
<i><b></b></i><!--1--><i><b></b></i><!--2--><i><b></b></i><!--3--><i><b></b></i><!--4--><i><b></b></i><!--5--><i><b></b></i><!--6--><i><b></b></i><!--7--><i><b></b></i><!--8--><i><b></b></i><!--9--><i><b></b></i><!--10-->
<i><b></b></i><!--1--><i><b></b></i><!--2--><i><b></b></i><!--3--><i><b></b></i><!--4--><i><b></b></i><!--5--><i><b></b></i><!--6--><i><b></b></i><!--7--><i><b></b></i><!--8--><i><b></b></i><!--9--><i><b></b></i><!--10-->
<i><b></b></i><!--1--><i><b></b></i><!--2--><i><b></b></i><!--3--><i><b></b></i><!--4--><i><b></b></i><!--5--><i><b></b></i><!--6--><i><b></b></i><!--7--><i><b></b></i><!--8--><i><b></b></i><!--9--><i><b></b></i><!--10-->
<i><b></b></i><!--1--><i><b></b></i><!--2--><i><b></b></i><!--3--><i><b></b></i><!--4--><i><b></b></i><!--5--><i><b></b></i><!--6--><i><b></b></i><!--7--><i><b></b></i><!--8--><i><b></b></i><!--9--><i><b></b></i><!--10-->
<i><b></b></i><!--1--><i><b></b></i><!--2--><i><b></b></i><!--3--><i><b></b></i><!--4--><i><b></b></i><!--5--><i><b></b></i><!--6--><i><b></b></i><!--7--><i><b></b></i><!--8--><i><b></b></i><!--9--><i><b></b></i><!--10-->
<i><b></b></i><!--1--><i><b></b></i><!--2--><i><b></b></i><!--3--><i><b></b></i><!--4--><i><b></b></i><!--5--><i><b></b></i><!--6--><i><b></b></i><!--7--><i><b></b></i><!--8--><i><b></b></i><!--9--><i><b></b></i><!--10-->
<i><b></b></i><!--1--><i><b></b></i><!--2--><i><b></b></i><!--3--><i><b></b></i><!--4--><i><b></b></i><!--5--><i><b></b></i><!--6--><i><b></b></i><!--7--><i><b></b></i><!--8--><i><b></b></i><!--9--><i><b></b></i><!--10-->
<i><b></b></i><!--1--><i><b></b></i><!--2--><i><b></b></i><!--3--><i><b></b></i><!--4--><i><b></b></i><!--5--><i><b></b></i><!--6--><i><b></b></i><!--7--><i><b></b></i><!--8--><i><b></b></i><!--9--><i><b></b></i><!--10-->
<i><b></b></i><!--1--><i><b></b></i><!--2--><i><b></b></i><!--3--><i><b></b></i><!--4--><i><b></b></i><!--5--><i><b></b></i><!--6--><i><b></b></i><!--7--><i><b></b></i><!--8--><i><b></b></i><!--9--><i><b></b></i><!--10-->
<i><b></b></i><!--1--><i><b></b></i><!--2--><i><b></b></i><!--3--><i><b></b></i><!--4--><i><b></b></i><!--5--><i><b></b></i><!--6--><i><b></b></i><!--7--><i><b></b></i><!--8--><i><b></b></i><!--9--><i><b></b></i><!--10-->
</div>
<div id="ManualLogin" class="box" style="border: none;">
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-group">
<label class="control-label" style="color:white;">Username</label>
@Html.TextBox("username", null, new { id = "username", @class = "form-control", @Value="us" })
</div>
<div class="form-group">
<label class="control-label" style="color:white;">Password</label>
@Html.TextBox("password", null, new { id = "password", @class = "form-control", @Value = "pwd" })
</div>
<div class="text-center" style="margin-top:40px;">
<input type="button" id="ManualLoginBtn" value="Sign in" class="btn btn-primary" />
<br />
<input type="button" id="AutoLoginBtn" value="Auto Authenticate" class="btn btn-default" />
<input type="button" id="ForgotLoginBtn" value="Forgot Credentials" class="btn btn-default" />
</div>
}
</div>
<div id="ForgotLogin" class="box" style="border: none;">
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-group">
<label class="control-label" style="color:white;">Email</label>
@Html.TextBox("email", null, new { id = "email", @class = "form-control", @Value = "jhjhblah" })
</div>
<div class="text-center" style="margin-top:40px;">
<input type="button" id="BackToLoginBtn" value="Back" class="btn btn-default" />
<input type="button" id="ForgotSubmitBtn" value="Submit" class="btn btn-primary" />
</div>
}
</div>
</div>
</div>
<script>
$(document).ready(function () {
var spinnerItems = $("#Spinner i b");
$("#MainLoginDiv").css("opacity", "1");
checkUserLoggedOut();
function checkUserLoggedOut() {
$.ajax({
//First need to check for logged off
url: '@Url.Action("UserLoggedOut", "Login", new { })',
success: function (data) {
if (data.result == false) {
showAutoAuthenticate();
}
else {
showManualForm();
}
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert("Error: " + errorThrown + " :-: " + textStatus);
}
});
}
function showAutoAuthenticate() {
$("#LoginHeader").text("Auto Authenticating");
$("#ManualLogin").css("opacity", "0");
setTimeout(function () { $("#ManualLogin").css("display", "none"); }, 550);
$("#Spinner").css("opacity", "1");
spinnerItems.each(function () {
$(this).addClass("spinAnimation");
})
$.ajax({
url: '@Url.Action("UserAutoAuthenticate", "Login", new { })',
success: function (data) {
if (data.result == false) {
//Switch to manual
//showForgotLogin();
showManualForm();
}
else {
//Remove login
$("#AutoLogin").css("opacity", "0");
spinnerItems.each(function () {
$(this).removeClass("spinAnimation");
})
}
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert("Error in showAutoAuthenticate(): " + errorThrown + " :-: " + textStatus);
}
});
}
function showManualAuthenticate() {
$("#LoginHeader").text("Authenticating");
$("#ManualLogin").css("opacity", "0");
setTimeout(function () { $("#ManualLogin").css("display", "none"); }, 550);
$("#Spinner").css("opacity", "1");
spinnerItems.each(function () {
$(this).addClass("spinAnimation");
})
$.ajax({
url: '@Url.Action("UserManualAuthenticate", "Login", new { })',
success: function (data) {
if (data.result == false) {
//Switch to manual
//showForgotLogin();
showManualForm();
}
else {
//Remove login
$("#AutoLogin").css("opacity", "0");
spinnerItems.each(function () {
$(this).removeClass("spinAnimation");
})
}
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert("Error in showManualAuthenticate(): " + errorThrown + " :-: " + textStatus);
}
});
}
function showForgottenProcessing() {
$("#ForgotLogin").css("opacity", "0");
setTimeout(function () { $("#ForgotLogin").css("display", "none"); }, 550);
$("#Spinner").css("opacity", "1");
spinnerItems.each(function () {
$(this).addClass("spinAnimation");
})
$.ajax({
url: '@Url.Action("SendUserCredentials", "Login", new { })',
success: function (data) {
if (data.result == false) {
//Switch to manual
showForgotLoginForm();
}
else {
//Go back to login
showManualForm();
}
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert("Error in showManualAuthenticate(): " + errorThrown + " :-: " + textStatus);
}
});
}
function showManualForm() {
$("#Spinner").css("opacity", "0");
spinnerItems.each(function () {
$(this).removeClass("spinAnimation");
})
$("#ForgotLogin").css("opacity", "0");
setTimeout(function () { $("#ForgotLogin").css("display", "none"); }, 550);
$("#LoginHeader").text("Login");
$("#ManualLogin").css("display", "block");
$("#ManualLogin").css("opacity", "1");
}
function showForgotLoginForm() {
$("#Spinner").css("opacity", "0");
spinnerItems.each(function () {
$(this).removeClass("spinAnimation");
})
$("#ManualLogin").css("opacity", "0");
setTimeout(function () { $("#ManualLogin").css("display", "none"); }, 550);
$("#LoginHeader").text("Retrieve Credentials");
$("#ForgotLogin").css("display", "block");
$("#ForgotLogin").css("opacity", "1");
}
$("#AutoLoginBtn").click(function () {
showAutoAuthenticate();
});
$("#ForgotLoginBtn").click(function () {
showForgotLoginForm();
});
$("#BackToLoginBtn").click(function () {
showManualForm();
});
$("#ManualLoginBtn").click(function () {
showManualAuthenticate();
});
$("#ForgotSubmitBtn").click(function () {
showForgottenProcessing();
});
})
</script>
Upvotes: 2
Views: 395
Reputation: 24957
The [ChildActionOnly]
attribute usage ensures that an action method can be called only as a child method from a parent view (i.e. disables direct navigation to load partial view like /Login/LoginDisplay
), and usually used to render partial view with RenderAction()
helper:
Any method that is marked with
ChildActionOnlyAttribute
can be called only with the Action or RenderAction HTML extension methods.
Since you're not calling the partial view by RenderAction()
but with AJAX which requires direct URL navigation in url
setting, the ChildActionOnlyAttribute
immediately prevents respond to request of that URL and runtime error Child action accessible only by a child request will be thrown (shown as "Internal Server Error" in AJAX result).
Hence, the controller action should not use [ChildActionOnly]
attribute:
[HttpGet]
public ActionResult LoginDisplay()
{
return PartialView("_LoginDisplay");
}
And the AJAX call should be like this:
function showLoginPartial() {
$.ajax({
url: '@Url.Action("LoginDisplay", "Login")',
type: 'GET',
success: function (response) {
$('#ib-container').html(response);
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
//Error displays
alert("Error in showLoginPartial(): " + errorThrown + " :-: " + textStatus);
}
});
}
References:
System.Web.Mvc.ChildActionOnlyAttribute Class
Upvotes: 2