CORS error when trying to redirect user from a partial view - ajax

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.

Related

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 !!

Parital view show login page with fullsite if session out after computer left idle for long time

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>

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..

asp.net mvc3 RouteToAction() not taking me anywhere

I'm using jquerymobile and asp.net MVC3 razor. I'm somewhat new to this, but figuring things out, I have a very basic route table, with just the ignore route for .axd resources and a default route:
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "", UrlParameter.Optional }
);
I have an action link that works in an .ascx page:
#Html.ActionLink("Log On", "LogOn", "Account", null, new { #class = "ui-btn-right" })
Now, when I get to the LogOn page, and I complete the account verification, I need to send them to the home page, /Home/Home which works if I type it in the address bar, but I can't seem to get my redirect working in the account controller: return RedirectToAction("Home", "Home");
Thanks for any help!
It sounds like maybe you're posting your form from /Account/LogOn via ajax. That means that when you return RedirectToAction("Home", "Home");, the page wouldn't change. So you just need to not use ajax on the form submit. If my guess is wrong, please post more code so we can get an idea of what the problem is.
It appears from the documentation that jQuery mobile handles form posts via ajax automatically. To prevent this, add the data-ajax="false" attribute to the form element. Documentation here: http://jquerymobile.com/test/docs/forms/forms-sample.html
Given what's written in documentation, could you put your code into a form element and setting its action property to /Account/LogOn ? In order to do that, you may have to convert your ActionLink into a button.
You can check for ajax request in controller:
if(Request.IsAjaxRequest())
{
//send json object and do navigate in client
return Json(new {IsLogged = true});
}
else
{
//send redirect html code to browser
return RedirectToAction("Home", "Home");
}
and in client side, check for json result if you post form by jQuery ajax.
I'm not use jquerymobile so I don't know how it work in client side.

create a nested jQuery post in another post callback?

since I'm new in jquery, can you tell me how to redirect a page to another action method ?
I develop a MVC web application. I use jquery post method to do some validation, and when it return true, it will be redirect page to another one.
My problem is..when when I redirect page using window.location, it's works well in IE (IE 9). but didn't work on firefox & chrome.
So, I try to using jquery post method to redirect page from action method in my controller. I call redirect post method in a jquery post call back.
it is my code :
$.post(posturl, formData, function (result) {
if (result == 'True') {
$.post("/Controller/RedirectMethod", {_Action: 'Index', _Controller: 'Home'}, null);
}
else
alert('failed');
}
);
and this is my RedirectMethod :
[HttpPost]
public ActionResult RedirectMethod(string _Action, string _Controller)
{
return RedirectToAction(_Action, _Controller);
}
so how I should create a nested post in another post callback ?
or there is another way to redirect page ?
thanks,
You won't be able to do a RedirectToAction inside an Ajax request.
If you need the web page to change to a different location inside the Ajax response, use window.location as Ben suggested.
One thing to bear in mind is that you'll need to remove the 'HttpPost' action filter.

Resources