Having trouble calling next Action once a users login is validated. ERROR redirected you too many times - asp.net-mvc

I need to route to a new view once the login is validated. This is currently not working. My authenticateUser method is working correctly as i can see when debugging, but not sure how to get the redirect to work.
CONTROLLER
public ActionResult Login()
{
if (PCSSession.Current.IsAuthenticated)
{
return RedirectToAction("Landing", "Start");
}
else
{
return View();
}
}
[HttpPost]
public JsonResult AttemptToLogin(string username, string password)
{
try
{
return new JsonResult
{
Data = PCSSession.Current.AuthenticateUser(username, password)
};
}
catch (Exception ex)
{
return new JsonResult
{
Data = "Error occured while trying to login"
};
}
}
AJAX IN VIEW
<script type="text/javascript">
$("#btnLogin").click(function () {
$.post("/Login/AttemptToLogin",
{
username: $('#Username').val(),
password: $('#Password').val(),
},
function (data) {
if (data == "true") {
$("#loginForm").submit();
} else {
}
});
});

This is because of [HttpPost] attribute. There are two things you could do here
You can pass your url to client and the call navigate(), or window.location = myurl
OR
return Redirect(redirectUrl);
hope this helps.

In order fix my error of too many redirects, i had to change the redirecttoaction to just return view.
if (PCSSession.Current.IsAuthenticated)
{
return View("../Start/Landing");
}
else
{
return View("Login");
}

Related

RedirectToAction is returning HTML Content

In ASP.NET MVC, I am trying to implement user authentication. Credentials are stored in SQL table.
I have a login page, when user enters credentials I am calling the JavaScript function shown here. Instead of redirecting to home page, it is returning html content of home page. May I know what I am doing wrong?
$("#btnsubmit").click(function () {
$('#lblvalidationmsg').text("");
var username = $('#txtuserId').val();
var password = $('#txtpassword').val();
if (username != "" && password != "") {
var LoginInfo = {};
LoginInfo.UserName = username;
LoginInfo.Password = password;
LoginInfo.RedirectURL = getParameterByName("redirecturl");
$.ajax({
url: '/Users/IsValidUser',
method: 'POST',
// url: '#Url.Action("IsValidUser", "Users")',
// datatype: "html",
//contentType: 'application/json; charset=utf-8',
data: JSON.stringify(LoginInfo),
success: function (data) {
if (data == "True") {
$('#lblvalidationmsg').text("Sucess");
}
else {
$('#lblvalidationmsg').text("Invalid User Name or Password.");
}
},
error: function (jqXHR) {
$('#divErrorText').text(jqXHR.responseText);
$('#divError').show('fade');
}
});
}
});
My controller method.
[AllowAnonymous]
[HttpPost]
public ActionResult IsValidUser(LoginInfo loginInfo)
{
bool isvalid = false;
try
{
userhelper = new UserHelper();
isvalid = userhelper.IsValidUser(loginInfo.UserName, loginInfo.Password);
if (isvalid)
{
System.Web.Security.FormsAuthentication.SetAuthCookie(loginInfo.UserName, false);
if (string.IsNullOrEmpty(loginInfo.RedirectURL))
{
return RedirectToAction("Index", "Home");
}
}
}
catch(Exception ex)
{
}
return RedirectToAction("Login");
}
}

Return to same View if Data is not Found and Display Not Found Message in the same View

I have Search View Where user enters Employee ID, Upon Clicking Button an Action Method is Executed and user is Redirected to Employee Details View.
If Employee Id not Matches I want to Retain the Same Search View and display a Label with Employee Details not Found Message in MVC,
Please help on doing the above Fucntionality in my Controller.
[HttpGet]
public async Task<ActionResult> Details(string firstName)
{
var empDetails = await _context.EmpDetails
.FirstOrDefaultAsync(m => m.FirstName == firstName);
if (empDetails == null)
{
// ???
}
return View(empDetails);
}
It is good practice to have ViewModel classes. Make one, and use it to transfer domain objects and messages to your view. Like this:
class EmpDetailsViewModel
{
public EmpDetail Emp { get;set; }
public string Message { get;set; }
}
[HttpGet]
public async Task<ActionResult> Details(string firstName)
{
var vm = new EmpDetailsViewModel();
var empDetails = await _context.EmpDetails
.FirstOrDefaultAsync(m => m.FirstName == firstName);
if (empDetails == null)
{
vm.Message = "Employee not found (or whatever)"
}
else
{
vm.Emp = empDetails;
}
return View(vm);
}
Then, in your view, just do
if (Model.Emp == null)
{
<span>#Model.Message</span>
}
else
{
<div>Emp details stuff </div>
}
What I understand is you want to return a message when Employee is not found.
Try this
[HttpGet]
public async Task<ActionResult> Details(string firstName)
{
var empDetails = await _context.EmpDetails
.FirstOrDefaultAsync(m => m.FirstName == firstName);
if (empDetails == null)
{
return Content("Employee not found");
}
return View(empDetails);
}
In view extract the message from the response.
--Edit
You can do an Ajax call like below to this action method
<script type="text/javascript">
$(function () {
$("#btnGetDetails").click(function () {
$.ajax({
type: "GET",
url: "/Employee/Details",
data: '{firstName: "' + $("#txtSearch").val() + '" }',
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (response) {
alert(response.responseText);
},
failure: function (response) {
alert(response.responseText);
},
error: function (response) {
alert(response.responseText);
}
});
});
});
</script>
success call back will be triggered and the message will be available in the view. (Didn't test the script)

How to serve the View/Action with parameters from different controller without redirecting?

How to do it? Currently my code is like this:
public ActionResult Index()
{
try
{
return RedirectToAction("Page", "Content", new { url = "/Home.html" });
}
catch(Exception ex)
{
return View();
}
}

How to redirect an Ajax Method session on timeout

So I got a ajax method that returns a JSON result, but part of the method is to check if the session is valid.
So If a user refreshed a page, the ajax method is called, in which it throws an exception as the session has expired, now the method wants to return a JSON result, but instead I want to redirect them to the login page.
how do I do this?
public JsonResult GetClients()
{
var usertoken = new UserToken(this.User.Identity.Name);
if (usertoken.AccountId != null)
{
return new JsonResult() {Data = model, JsonRequestBehavior = JsonRequestBehavior.AllowGet};
}
else
{
//Redirect Here
}
AFAIK you would only be able to do this via JavaScript since your call is using ajax, the solution to the other post would not work since the redirect header would not be honored for an ajax request.
You might want to add a status or hasExpire property to your return result:
[HttpPost]
public ActionResult GetClients()
{
var usertoken = new UserToken(this.User.Identity.Name);
if (usertoken.AccountId != null)
{
return Json(new { data = model, status = true });
}
else
{
return Json(new { data = null, status = false });
}
On your ajax call:
$.ajax('/controller/getclients', { }, function(data) {
if(data.status == true) {
// same as before you've got your model in data.data...
} else {
document.location.href = '/account/login';
}
});
Hope that help.
In Controller code, check for session validity. For example
if (Session["UserName"] == null)
{
return Json(new
{
redirectUrl = ConfigurationManager.AppSettings["logOffUrl"].ToString(),
isTimeout = true
});
}
In .js file check like the following
success: function (data) {
if (data != '' && typeof data != 'undefined') {
if (data.isTimeout) {
window.location.href = data.redirectUrl;
return;
}

ASP.NET MVC Ajax Error handling

How do I handle exceptions thrown in a controller when jquery ajax calls an action?
For example, I would like a global javascript code that gets executed on any kind of server exception during an ajax call which displays the exception message if in debug mode or just a normal error message.
On the client side, I will call a function on the ajax error.
On the server side, Do I need to write a custom actionfilter?
If the server sends some status code different than 200, the error callback is executed:
$.ajax({
url: '/foo',
success: function(result) {
alert('yeap');
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
alert('oops, something bad happened');
}
});
and to register a global error handler you could use the $.ajaxSetup() method:
$.ajaxSetup({
error: function(XMLHttpRequest, textStatus, errorThrown) {
alert('oops, something bad happened');
}
});
Another way is to use JSON. So you could write a custom action filter on the server which catches exception and transforms them into JSON response:
public class MyErrorHandlerAttribute : FilterAttribute, IExceptionFilter
{
public void OnException(ExceptionContext filterContext)
{
filterContext.ExceptionHandled = true;
filterContext.Result = new JsonResult
{
Data = new { success = false, error = filterContext.Exception.ToString() },
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}
}
and then decorate your controller action with this attribute:
[MyErrorHandler]
public ActionResult Foo(string id)
{
if (string.IsNullOrEmpty(id))
{
throw new Exception("oh no");
}
return Json(new { success = true });
}
and finally invoke it:
$.getJSON('/home/foo', { id: null }, function (result) {
if (!result.success) {
alert(result.error);
} else {
// handle the success
}
});
After googling I write a simple Exception handing based on MVC Action Filter:
public class HandleExceptionAttribute : HandleErrorAttribute
{
public override void OnException(ExceptionContext filterContext)
{
if (filterContext.HttpContext.Request.IsAjaxRequest() && filterContext.Exception != null)
{
filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
filterContext.Result = new JsonResult
{
JsonRequestBehavior = JsonRequestBehavior.AllowGet,
Data = new
{
filterContext.Exception.Message,
filterContext.Exception.StackTrace
}
};
filterContext.ExceptionHandled = true;
}
else
{
base.OnException(filterContext);
}
}
}
and write in global.ascx:
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleExceptionAttribute());
}
and then write this script on the layout or Master page:
<script type="text/javascript">
$(document).ajaxError(function (e, jqxhr, settings, exception) {
e.stopPropagation();
if (jqxhr != null)
alert(jqxhr.responseText);
});
</script>
Finally you should turn on custom error.
and then enjoy it :)
Unfortunately, neither of answers are good for me. Surprisingly the solution is much simpler. Return from controller:
return new HttpStatusCodeResult(HttpStatusCode.BadRequest, e.Response.ReasonPhrase);
And handle it as standard HTTP error on client as you like.
I did a quick solution because I was short of time and it worked ok. Although I think the better option is use an Exception Filter, maybe my solution can help in the case that a simple solution is needed.
I did the following. In the controller method I returned a JsonResult with a property "Success" inside the Data:
[HttpPut]
public JsonResult UpdateEmployeeConfig(EmployeConfig employeToSave)
{
if (!ModelState.IsValid)
{
return new JsonResult
{
Data = new { ErrorMessage = "Model is not valid", Success = false },
ContentEncoding = System.Text.Encoding.UTF8,
JsonRequestBehavior = JsonRequestBehavior.DenyGet
};
}
try
{
MyDbContext db = new MyDbContext();
db.Entry(employeToSave).State = EntityState.Modified;
db.SaveChanges();
DTO.EmployeConfig user = (DTO.EmployeConfig)Session["EmployeLoggin"];
if (employeToSave.Id == user.Id)
{
user.Company = employeToSave.Company;
user.Language = employeToSave.Language;
user.Money = employeToSave.Money;
user.CostCenter = employeToSave.CostCenter;
Session["EmployeLoggin"] = user;
}
}
catch (Exception ex)
{
return new JsonResult
{
Data = new { ErrorMessage = ex.Message, Success = false },
ContentEncoding = System.Text.Encoding.UTF8,
JsonRequestBehavior = JsonRequestBehavior.DenyGet
};
}
return new JsonResult() { Data = new { Success = true }, };
}
Later in the ajax call I just asked for this property to know if I had an exception:
$.ajax({
url: 'UpdateEmployeeConfig',
type: 'PUT',
data: JSON.stringify(EmployeConfig),
contentType: "application/json;charset=utf-8",
success: function (data) {
if (data.Success) {
//This is for the example. Please do something prettier for the user, :)
alert('All was really ok');
}
else {
alert('Oups.. we had errors: ' + data.ErrorMessage);
}
},
error: function (request, status, error) {
alert('oh, errors here. The call to the server is not working.')
}
});
Hope this helps. Happy code! :P
In agreement with aleho's response here's a complete example. It works like a charm and is super simple.
Controller code
[HttpGet]
public async Task<ActionResult> ChildItems()
{
var client = TranslationDataHttpClient.GetClient();
HttpResponseMessage response = await client.GetAsync("childItems);
if (response.IsSuccessStatusCode)
{
string content = response.Content.ReadAsStringAsync().Result;
List<WorkflowItem> parameters = JsonConvert.DeserializeObject<List<WorkflowItem>>(content);
return Json(content, JsonRequestBehavior.AllowGet);
}
else
{
return new HttpStatusCodeResult(response.StatusCode, response.ReasonPhrase);
}
}
}
Javascript code in the view
var url = '#Html.Raw(#Url.Action("ChildItems", "WorkflowItemModal")';
$.ajax({
type: "GET",
dataType: "json",
url: url,
contentType: "application/json; charset=utf-8",
success: function (data) {
// Do something with the returned data
},
error: function (xhr, status, error) {
// Handle the error.
}
});
Hope this helps someone else!
For handling errors from ajax calls on the client side, you assign a function to the error option of the ajax call.
To set a default globally, you can use the function described here:
http://api.jquery.com/jQuery.ajaxSetup.

Resources