Parital view show login page with fullsite if session out after computer left idle for long time - asp.net-mvc-3

I have created an asp.net mvc razor application, in which I load a partial view in a div, which can be accessed after login.
<% using (Ajax.BeginForm("Showproducts", "Home", new AjaxOptions {
UpdateTargetId = "resdiv", OnBegin = "fstart()", OnSuccess = "fend()"
}, new { id = "_myform" }))
{ %>
.....
<% } %>
When a user leaves their computer for a long time (which makes the session time out automatically) and then clicks the submit button, the resdiv is filled with the full site with the login panel. I want to show the full site with login panel NOT in the resdiv. Is there any way to avoid this behavior?

Is there any way to avoid this behavior?
Yes, there is a way. I would recommend you reading the following blog post in which Phil Haack illustrates a very nice technique allowing you to override the Forms Authentication Module for AJAX requests and be able to send a 401 status code instead of redirecting to the login page.
Then on the client side you could use a global AJAX handler where you could test the status code and if it is 401 redirect to the logon page.
For example once you have installed the AspNetHaack NuGet you could add the following global error handler to your view:
<script type="text/javascript">
$(document).ajaxError(function(event, jqXHR, ajaxSettings, thrownError) {
if (jqXHR.status == 401) {
// not authenticated => redirect to login page:
window.location.href = '#FormsAuthentication.LoginUrl';
}
});
</script>

Related

CORS error when trying to redirect user from a partial view

I am working on an application written in ASP.NET MVC5 which require the user to be log in. The authentication works with Central Authentication Service (CAS). On the homepage, I have several partial views :
Home page with partial views
I call a controller's action when I want to update the user's data.
It's working well, until the CAS session expires. If I try to refresh the partial views, I get an error :
"OPTIONS https://example.com/CAS/Authentication 403 (Forbidden)"
"Failed to load https://example.com/CAS/Authentication: Response for preflight has invalid HTTP status code 403"
I think it comes from the use of Ajax to refresh the partial view and it returns me the login page, which is not on the same domain. How can I overcome this issue ?
In my View I send the datas to the Controller with Ajax.BeginForm() and my controller returns a partial view, so that I don't need to completely refresh the page.
To overcome the Cross Origin Request error, I needed to handle the Ajax response. Instead of letting the login page being returned in the partial view, I call a Javascript function on the OnComplete event, checking the status code of the response.
In my partial view :
AjaxOptions ajaxOptions = new AjaxOptions
{
HttpMethod = "POST",
OnComplete = "redirectToLoginPage"
};
using (Ajax.BeginForm("ActionName", "ControllerName", null, ajaxOptions))
{
<button type="submit">Submit</button>
}
On click on submit, it will execute the action "ActionName" from the controller "ControllerName". Then, it will fire the Javascript function "redirectToLoginPage", which is :
function redirectToLoginPage(xhr) {
if (xhr.status == 200) {
//Whatever
}
else
{
window.location.replace("https://login.example/");
}
}
This do the trick.

Spring-Boot: Redirect and Refresh model and page

I have a spring-boot application, with theyemleaf. I repeatedly update the page, and redirect it to the same page, so i expect that the elements of the page get updated:
#GetMapping("/suggested-events/vote/{eventId}")
public String voteForEvents(Model model,
#PathVariable("eventId") Long eventId,
#RequestParam(value = "message", required = false) String message ) {
log.info("The message is: "+message);
SuggestedEvent event = suggestedEventService.findSuggestedEventById(eventId);
ArrayList<SuggestedEvent> events = suggestedEventService.findSuggestedEventsByArea(event.getArea());
model.addAttribute("mainEvent",event);
model.addAttribute("events",events);
model.addAttribute("message",message);
return "/suggested-event/vote";
}
and when a button get pushed in the view it triggers the below post method:
#PostMapping("/suggested-events/vote")
public String voteForASuggestedEvent(RedirectAttributes redirectAttributes){
log.info("You have made a vote");
redirectAttributes.addAttribute("message", "Success");
return "redirect:/suggested-events/vote/1";
}
This second controller method, performs an operation an makes a message, and redirects it to the first method. So, it successfully redirected to the first method and it logs
log.info("The message is: "+message);
but it does not refresh my page, and i do not get the message as model?
When i redirect to the first method, i expect it adds the message to my models:
model.addAttribute("message",message);
But it does not added to my page
and when a button get pushed in the view it triggers the below post
method:
It sounds like this trigger is using AJAX, rather than a form submit. Doing so would match the symptoms you describe.
If you POST to /suggested-events/vote using AJAX, the server will return a 302, and the browser will follow it. However, the response for that 302 is still the result of an AJAX call. You have access to it in your success callback, but the browser isn't going to render it for you.
but it does not refresh my page
If a 302 doesn't cause your page to re-render, this also suggests you're using AJAX.
If you actually use a form submit instead, the browser will re-render using the markup returned by the successful redirect.
This can be verified by using the following two buttons in your vote.html:
<form action="http://localhost:8080/suggested-events/vote" method="POST">
<input type="submit" text="Submit" />
</form>
<button onclick="postmessage();" >Button</button>
<script>
function postmessage() {
$.ajax({
method: 'POST',
data: {},
url: 'http://localhost:8080/suggested-events/vote'
});
}
</script>
The first button will work as expected, and the second button matches the symptoms you describe.
If you are already using a form, please update the question with it (or better yet, the entire Thymeleaf template).
I had the same problem as OP described and Mike's explanation brought me in the right direction.
I am reading a db-table and populating it with thymeleaf using th:each. I wanted to add a javascript-confirmation before deleting an item. Sending an ajax GET without an event-listener and reloading with location.reload(true) didn't reach the #GetMapping("/delete/{id}") in the controller.
This SO-thread gave me the answer to the ajax-call.
<a class="btn btn-danger" href="#" th:onclick="|confirmDeletion('${u.id}')|"></a>
<script th:inline="javascript">
function confirmDeletion(id) {
if (confirm("Delete this id? " + id)) {
var http = new XMLHttpRequest();
http.open("GET", "/delete/" + id, true);
http.addEventListener("readystatechange", function() {
if (http.readyState === 4 && http.status === 200) {
window.location.reload(true);
}
});
http.send();
}
}
</script>
there are many ways to redirect page in Spring, but be sure if the model attribute off message its passing correctly to FrontEnd or passing like parameter to another handler , you can see this document : http://javainsimpleway.com/spring-mvc-redirecting-model-attributes-from-one-controller-to-other-controller/ , hope this is useful !!

.Net MVC Partial View load login page when session expires

I am building a web application using .net MVC 4.
I have ajax form to edit data.
If the user is idle for 15 mins it will expire the session of the user. When that happens if user click edit button it loads the login page inside the partial content hence now the current session expires.
Edit Link - cshtml code
#Ajax.ActionLink("Edit", MVC.Admin.Material.ActionNames.TagEditorPanel, MVC.Admin.Material.Name, new { isView = "false", id = Model.ID.ToString() }, new AjaxOptions { HttpMethod = "GET", UpdateTargetId = "materialTagBox", InsertionMode = InsertionMode.Replace }, new { #class = "editlinks" })
Controller/Action Code
[Authorize]
public virtual ActionResult TagEditorPanel(bool isView, int id)
{
//do something
return PartialView(MVC.Admin.Material.Views._tag, response);
}
Web.config
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" timeout="2880" />
</authentication>
I understand why it is happening. I don't know how to resolve it. I want to prevent it and I want to redirect user to login page directly. How can I achieve this?
Thanks inadvance..!!!
Maybe a hacky answer, but you can change the redirect location in forms authentication to a page that sets the window location to the login page with javascript.
Web Config
<authentication mode="Forms">
<forms loginUrl="~/Account/RedirectToLogin" timeout="2880" />
</authentication>
Account Controller
public ActionResult RedirectToLogin()
{
return PartialView("_RedirectToLogin");
}
_RedirectToLogin View
<script>
window.location = '#Url.Action("Login", "Account")';
</script>
The issue is your call is intercepted by [Authorize] and sends the login page even before your action method code is called. One way to sort this out is to create a custom action filter to check the timeout and do a hard redirect to login page. Following post has a good write up which may help you in creating and registering the filter
http://www.codeblockdrive.com/2012/12/mvc-custom-filters-session-timeout.html
Best of luck
You may want to check the answer to this (similar) question.
ASP.NET MVC Partial view ajax post?
Basically it says that you should avoid making ajax calls to functions that may redirect because of this and other problems.
You can avoid the problem that you are having by authorizing / checking the expiration manually in your function, and then returning redirect information that can be applied to the whole page.
I have used this approach, and it works well.
Inspired by kramwens answer, one could avoid making an extra RedirectToLogin view (and controller action) and just put the following in you original Login view:
<script>
if (window.location != '#string.Format("{0}://{1}{2}",Request.Url.Scheme, Request.Url.Authority,Url.Content("~/Account/Login"))')
window.location = '#Url.Action("Login", "Account")';
</script>
This tests the current window.location and if it is not as expected, it sets it as expected.
I know, my js is a bit hacky and crappy, but it does the work :)
I Have simple way find for partial view session expired.
Simple One Action created then this view java script windows.load() call then url will be pass to this login page.
//in Controller one Action Created.
<script type="text/javascript">
window.location = '#Url.Action("Login", "LogIn")';
</script>
Public ActionResult SessionExpire()
{
return View();
}
//Redirect to login from partail view after session is null:
return Redirect("~/OrderPlace/Sessionview");
My solution is to use some c# code whenever possible. I can get the controller and view name, check to see of they are what they should be, and if not redirect to the proper.
var controllerName = ViewContext.RouteData.GetRequiredString("controller");
var actionName = ViewContext.RouteData.GetRequiredString("action");
I then use the following to go to the proper URL:
if (controllerName != "members" && actionName != "logon")
{
#{ Response.Redirect("~/Members/Logon");}
}

how can I redirect in .jsp while working with Ajax

I am developing application using Ajax and jsp.
My index.jsp page has HTML code for Login and some Ajax code in javascript. Ajax will call my another CheckLogin.jsp page
CheckLogin.jsp page checks on server for valid username and password. It returns "success" if it's valid otherwise will return message stating "username or password is not valid."
Now, when username and passwrod is valid, instead of success, I want to redirect the page to "Home.jsp" what should I do?
I am new to jsp. I appreciate your help on this.
JSP code gets run once on the server before it goes to the client, so JSP/JSTL cannot do a redirect following the success or otherwise of an AJAX call (without a full page refresh - which obviates the use of AJAX). You should to do the redirect with Javascript:
if (success) {
var successUrl = "Home.jsp"; // might be a good idea to return this URL in the successful AJAX call
window.location.href = successUrl;
}
On successful AJAX call/validation, the browser window will reload with the new URL (effectively a redirect).
Since I don't see your code, you can integrate this somewhere inside your validation :
<%
pageContext.forward("logged.jsp");
%>
function Edit() {
var allVals = $('#NEWFORMCampaignID').val();
if (allVals > 0) {
window.location = '/SMS/PrepareSMS?id='+allVals;
}
else
alert("Invalid campaign to Edit")
}
In order to redirect using Button click and pass some parameters, you can call the Controller Path(#RequestMapping(value="/SMS/PrepareSMS")) and then handle it there..

AJAX not working on MVC Page

I am using MVC3 with Razor. I have one Action which want to load using AJAX. I am using jQuery UIblock plugin http://jquery.malsup.com/block/# to show some wait image to user.
The View corresponding to action is as shown below:
#using (Ajax.BeginForm("Search", "Home", new AjaxOptions() { HttpMethod = "GET", OnBegin = "BlockUI", OnComplete = "UnBlockUI", UpdateTargetId = "page" }))
{
...................
}
Javascript code is as shown below:
<script type="text/javascript">
function BlockUI() {
$.blockUI({ message: "<img src='#Url.Content("~/Content/images/loading.gif")' />" });
}
function UnBlockUI() {
$.unblockUI({ message: "Done....." });
}
Now I am redirecting to Action using a link as
location.href = '#Url.Content("~/Home/Search/")';
When the search view is loading, I cannot see any Div showing Loading image.
The same thing is working on other page, the only difference is that on other pages the Image is coming on POSTBACK.
Additionally, all Ajax POST operations are working but not GET ones.
What is the problem with Search page here ??
Thanks.
Now I am redirecting to Action using a link as
location.href = '#Url.Content("~/Home/Search/")';
The keyword here is I am redirecting. It's not I am sending an AJAX request. When you redirect, the browser simply stops running any scripts on the current page and redirects away to the target location. The OnBegin and OnComplete methods that you have subscribed to will never fire when you redirect which is why you are not seeing any blockUI.

Resources