how to maintain session for 2 different browsers? - asp.net-mvc-3

I done project in ASP.net MVC3. In my project i create a session as follows in Home Controller
if (Session["ulclass"] == null)
{
Session["ulclass"] = "list";
}
I use this session to my Product List page.. as a class for div tag as follows..
<div id="listheading" class="listHead" #if (Session["ulclass"].ToString() == "grid")
{
<text>style = "display:none;";</text>
}>
When i copy this Productlist URL from FireFox to Chrome...
session value not come.. it produce the error...
Can any one help this ?

You can use cookieless sessions. That way the session id is sent in the URL instead of a cookie, so then you could just copy the URL anywhere and you are still in the same session.
Put this in web.config:
<sessionState cookieless="true" />
(The drawback is of course that anyone can copy the URL anywhere and still be in your session...)
More about cookieless session: http://msdn.microsoft.com/en-us/library/aa479314.aspx

Use Convert.ToString(Session["ulclass"]) == "grid" to avoid error first, and then add in we.config

Related

.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");}
}

JSF AJAX and normal redirect to login and back to previous page

Current status :
If any session time out occurs, redirectToLogin function in FacesAjaxAwareUserFilter will be executed. From there I can redirect to any page I need. I get the URI in all cases.
It's all working fine and big thanks to BalusC. :)
Now the second part which makes the issue
Redirect to login and come back to the previous page.
For Eg :
Page 5----> Login------> Page 5
I have appended the redirect URI to the login URI and retrieved the values from the bean.
But the problem is that I have 2 pages before the user login. A login mode selection page (ie; google authentication or default login) and the page that reads the username and password.
How can I pass the redirect URI through both the pages.?
This is the code I have used to redirect at Ajax time out and in normal session time out.
Class FacesAjaxAwareUserFilter
if ("partial/ajax".equals(request.getHeader("Faces-Request"))) {
res.setContentType("text/xml");
res.setCharacterEncoding("UTF-8");
res.getWriter().printf(FACES_REDIRECT_XML, request.getContextPath() + getLoginUrl()+"?redirectUrlPattern="+request.getRequestURI());
}
else {
if (request.getRequestedSessionId()!=null && (!SecurityUtils.getSubject().isAuthenticated() || !request.isRequestedSessionIdValid())) {
response.sendRedirect(getLoginUrl()+"?redirectUrlPattern="+request.getRequestURI());
return;
}
super.redirectToLogin(req, res);
}
Method used is FullAjaxExceptionHandlerFactory in Omniface.
I have used a method of appending the values to the URI, but it fails to identify whether the session is expired or a session not created (when a user logs in at first).
Problem Code
if (request.getRequestedSessionId()!=null && (!SecurityUtils.getSubject().isAuthenticated() || !request.isRequestedSessionIdValid()))
I am looking for a way to identify the expired session from new session created before login.
Wish to implement this in a Better Way.
A method which will not append present URI with the redirect URL is most welcomed.
I have founded out a solution but still i don't find it as the best solution. Any other answer for doing it is greatly appreciated.
Step 1
Configure the application to detect Ajax Timeout and normal timeout. This is how i did it..!!
Step 2
Finding the URI when session timeout occurs, using this.
FacesAjaxAwareUserFilter will grab the ServletRequest and ServletResponse for you.
form that you can convert that to HttpServletRequest and HttpServletResponse using this
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response= (HttpServletResponse) res;
The request.getRequestURI() will get you the redirect URI
String redirectURI=request.getRequestURI();
Now you want to save this to some storage so that you can use it in any place you want. The only way i found is to append it with URL using this.
res.getWriter().printf(FACES_REDIRECT_XML, request.getContextPath() + "/sessionexpired"+"?redirectUrlPattern="+request.getRequestURI());
or
response.sendRedirect("/sessionexpired"+"?redirectUrlPattern="+request.getRequestURI());
Now on the page load of my sessionExpiry page bean, i used this to grab the value passed through the URL
redirectUrl=FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("redirectUrlPattern");
Now using JavaScript i set that value of redirectUrl to localStorage. This is how you can save values to local storage.
This is my sessionexpiry.xhtml page.
<script type="text/javascript">
function setRedirectURIToLocalStorage(){
if(typeof(Storage)!=="undefined")
{
localStorage.redirectURI=document.getElementById("redirectUrl").value;
window.location.href="/login";
}
}
</script>
</h:head>
<h:body id="body" onload="setRedirectURIToLocalStorage()">
<f:view contentType="text/html">
<h:form prependId="false" >
<h:inputHidden id="redirectUrl" value="#{sessionExpBean.redirectUrl}" />
<h:outputText value="Session Expired... Redirecting...!!"></h:outputText>
</h:form>
</f:view>
</h:body>
The page will call setRedirectURIToLocalStorage() function onLoad
and then it set the values to the localStorage. Thus the redirect
value is available all across the browser. You can use that in any
page you need.!! All you need to do is to check in this variable
localStorage.redirectURI

How to execute an action without going to another view in grails?

I have a code that starts the server and stops the server. However when i press the button the server gets started but it also redirects me to a new view. The code in controller i have is
def test= amazonWebService.ec2.startInstances(new StartInstancesRequest([InstanceToStart]))
I want to execute test when button is pressed without going to new view. The code I have in my gsp page is
<g:link action="test">
<input type="button" value="Start Server" class="button" id="startServer1" />
</g:link>
If you don't mind the page refreshing, in your test action, redirect to the same view you came from. So assuming you got to your current view via index:
class SomeController {
def index() {
// index.gsp rendered via convention
}
def test() {
// execute your code then
redirect action: index, params: params
}
}
You're other option is to submit an Ajax request when the link is clicked and not have to refresh the page at all.
Use a remote function, see here http://grails.org/doc/2.1.0/ref/Tags/remoteFunction.html
Following is the alternative answer to the question.
By default Grails view resolver tries to find a view similar to the action name. In your case, Grails is trying to find test.gsp and if it is there in your repository it renders that. You can override this behaviour by using the Grails URL mappings feature. There you will get to specify which view should be rendered for a certain action.
class UrlMappings {
static mappings = {
"/$controller/$action?/$id?"{
constraints {
// apply constraints here
}
}
"/"(view:"/index")
"500"(view:'/error')
}
}
For further information visit : http://grails.org/doc/2.2.x/ref/Plug-ins/URL%20mappings.html

Safari iFrame cookie issue

I realize that there are several questions related to this; however I've been going crazy trying to make this work. Simply put, I have an MVC3 application that lives on our company's server, and it is served up in an iFrame on a client's URL. All is fine and dandy with every other browser, execpt for Safari, which has the whole "no third party cookies" setting turned on by default.
So here's what I've tried so far (we have custom libraries, so some of these functions are specific to our stuff):
View:
#if ((HttpContext.Current.Request.UserAgent.ToLower().IndexOf("safari") >= 0) && HttpContext.Current.Request.Cookies["safari_cookie_set"] == null)
{
using (Html.BeginRouteFormSSL(RouteNames.SafariRedirect, FormMethod.Post, new { id = "safari-fix-form" }))
{ <input type="submit" value="Go!" /> }
}
Controller:
[AcceptVerbs(HttpVerbs.Post)]
public virtual ActionResult SafariRedirect()
{
ActionResult result = null;
Response.Cookies.Add(new HttpCookie("safari_cookie_set", "cookie ok"));
result = RedirectToRouteNoSSL(Index);
return result;
}
Javascript:
safariValidate: function(){
if ($.browser.safari == true && document.cookie.indexOf("safari_cookie_set") == -1){
$("#safari-fix-form").submit();
}
}
So initially, the premise was to automatically post to the iframe using javascript (thus the .submit()). It seemed to work, for a day or so. Now, it doesn't matter how I post (notice the input button here...), a cookie will NOT be set within an iframe.
Any ideas?
After much deliberation and fighting with different browsers, our company finally decided to ditch cookies in favor of using database based sessions. This completely resolves the issue since we are dealing with a third party website hosting our site in an iframe.
Hopefully this will help others - there is no clean way to use cookies in an iframe.

ColdFusion change session variable on a page change

Is there a way in ColdFusion to change a session variable after a page change? - Especially after a page change to a specific page?
Goes to one page --> change session variable
Goes to a different page --> change session variable to something else
Can you add code to the existing page? When importantpage.cfm is loaded you could run this at the top of the page
<cfset session.variable = 'important page loaded'>
That should accomplish what you are looking for.
You could also add <cfset> tags to your application.cfm/cfc file
You can manage this in application.cfm or application.cfc and then this will carry over to every page and subfolder in your application. You would just do an if statement using the CGI variable for the name of the page.
<cfscript>
if (findnocase("page1",cgi.script_name)) {
session.myVar="Variable State 1";
} else if (findnocase("page2",cgi.script_name)) {
session.myVar="Variable State 2";
} else {
session.myVar="Variable State DEFAULT";
}
</cfscript>

Resources