I have one controller class with two action functions. One action is my login page with one view, and the other is my backend page with multiple views.
public ActionResult Login(...)
{
if (logged in or login success)
{
return RedirectToAction("Backend","Controller");
}
...
return View();
}
public ActionResult Backend(...)
{
if(session expired or not logged in)
{
return RedirectToAction("Login","Controller");
}
...
return View("someView");
}
The issue is when the backend action has to send the user to the login action and I want to show the user a message like "Session expired" on the login page.
As an example ViewBag only lives in the current session. But is there a similar and easy way to store information between sessions? So I can set a message in the backend, then redirect to login, and have the login read that message and display it in the view? Kinda like PersistentViewBag.
I really do not want to use get, post or cookies, as is a viable option but then I rather just have the login as its own view in the backend action instead.
You can simply use the querystring for passing data when you are redirecting to the login page.
public ActionResult Backend(...)
{
if(session expired or not logged in)
{
return RedirectToAction("Login","Controller",new { IsSessionExpired = true });
}
...
return View("someView");
}
In your Login action you can check the querystring and decide if you want to display the message.
Update
You can also use TempData if you do not want to use the querystring.
public ActionResult Backend(...)
{
if(session expired or not logged in)
{
TempData["IsSessionExpired"] = true;
return RedirectToAction("Login","Controller");
}
...
return View("someView");
}
Then you can check it in Login action:
if(TempData["IsSessionExpired"] != null)
{
//Show message
}
Related
I am using MVC3, ASP.NET4.5, C#, Razor, Ajax
I have implemented an Ajax.Actionlink. All works well.
However, since I am also using Membership Services, I will get logged out of the system if I do not use it for say 20 mins. If one is on the Ajax page, and one clicks an Ajax link, the Ajax returns, within the TargetDiv, the Login page and not the correct partial view.
I suspect that if the app has expired then the response needs to override the ajax response, and return the full login page.
How can I solve this please.
You can use a custom authorize attribute to handle the situation.
public class AjaxAuthorizeAttribute : AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
var request = filterContext.HttpContext.Request;
var response = filterContext.HttpContext.Response;
if (request.IsAjaxRequest())
{
response.StatusCode = 590; //custom status code, might as well be 401, dont know if that would violate any proncipal
filterContext.Result = new EmptyResult();
}
else
{
base.HandleUnauthorizedRequest(filterContext);
}
}
}
add some js codes in master page to handle the custom status code.
$(function () {
return $(document).ajaxError(function (e, xhr, opts) {
if (590 == xhr.status) {
return document.location = document.location;
}
});
});
use it as any [Authorize] attribute for the ajax actions you like to be authorized
public class HomeController : Controller
{
[AjaxAuthorize]
public JsonResult AjaxMethod()
{
return Json(new {message = "Hello"}, JsonRequestBehavior.AllowGet);
}
}
The custom Authorize filter will handle the unauthorized request and issue an empty
result with status code 590
The response will be caught as ajaxerror since the statuscode is 5**
The document will be reloaded (assuming the page is an authenticated one), as such will be redirected to login page.
Hope this helps
I have a number of MVC views that only make sense in the context of a workflow. E.g. user submits information on another page and is then redirected to a page which only display "success"..
Since the redirect is a GET, there is no way to stop users manually navigating to the page by adjusting their URL.
What should I do in this situation? Redirect to an error page, show a blank page?
In my opinion sucess information views should not have routes, as they are not intended to be served from a browser url. in our projects we usually return the success view directly from an post action.for example,
[HttpPost]
public ActionResult ChangePassword(ChangePasswordModel model)
{
if (ModelState.IsValid)
{
bool changePasswordSucceeded;
try
{
MembershipUser currentUser = Membership.GetUser(User.Identity.Name, userIsOnline: true);
changePasswordSucceeded = currentUser.ChangePassword(model.OldPassword, model.NewPassword);
}
catch (Exception)
{
changePasswordSucceeded = false;
}
if (changePasswordSucceeded)
{
var infoModel = new AnyInfoModel();
return View("ChangePasswordSuccess", infoModel); // This is not redirected, but success shown in the current route url.
}
else
{
ModelState.AddModelError("", "The current password is incorrect or the new password is invalid.");
}
}
return View(model);
}
But this has a drawback also, if an user accidentally hit he F5 button the browser, it will try to repost the form.
I'm using Facebook to preautheticate users, so when they visit a page, an ajax function is called to login the user, and the server will also check to see if the user is already authenticated to the site. These users have entries in the user database on the server.
The server side code is below, which is called by ajax. After that, is a second method I use to get more information on the user that is stored in the database.
When I call User.Identity.IsAuthticaed in the second method, in the same Controller, the User object is still null. The User object contains all the information in FBReg below.
Edit:
After further troubleshooting I found that the ActionResult that calls getUserInfo() has the User object populated. So I'm not sure why getUserInfo() has a null User. I guess I can just pass the object then, but I'm still just curious why this happens.
[HttpPost]
public String FBReg(FBInfo userinfo)
{
..
..
..
if (!User.Identity.IsAuthenticated)
{
if (ModelState.IsValid)
{
if (Membership.ValidateUser(userinfo.id, "FBPassword"))
{
FormsAuthentication.SetAuthCookie(userinfo.id, true);
var result = (from u in db.users where (u.username == userinfo.id) select u).FirstOrDefault();
result.LastLoginDate = DateTime.Now;
db.SaveChanges();
}
else
{
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
}
..
..
..
return "";
}
public UserRepository getUserInfo()
{
bool isauth = false;
try
{
if (User.Identity.IsAuthenticated) // User is always null even after FBReg has User as Authnticated with all the correct information
{
isauth = User.Identity.IsAuthenticated;
}
}
catch { }
// get user info from database to display on page
..
..
..
return userInfo;
}
I am using MVC3/Razor. But I don't understand why the previous page url appears when i redirecToAction.
Scenario: Once the user clicks on Signup from home page like "Account/Signup", the he would get RedirectToAction("AcceptCondition") so once the use accepts the condition and post then the user would get RedirectToAction("Signup") where i will check if he is coming from "AcceptCondition" page then he can proceed otherwise user will go back to "AcceptCondition" page. So when I redirect user from Signup page to AcceptCondition page the url in the address bar appears like "http://localhost:55104/Account/Signup" instead of "http://localhost:55104/Account/AcceptCondition"
I know that i can send user directly to "Account/AcceptCondition" when he click on the signup but I just followed upper scenario.
public ActionResult Signup(string ru)
{
if ((ru == "/Account/AcceptCondition") || (ru == "/Account/Signup"))
{
return View();
}
else
{
return RedirectToAction("AcceptCondition");
}
}
[HttpGet]
public ActionResult AcceptCondition()
{
return View();
}
[HttpPost]
public ActionResult AcceptCondition(AcceptConditionViewModel acceptCondiViewModel)
{
if (acceptCondiViewModel.TermAndCondi == true)
{
return RedirectToAction("Signup",
"Account",
new { ru = "/Account/AcceptCondition" });
}
else
{
return View();
}
}
Signup GET checks refers, if not AcceptCondition, then redirects to AcceptCondition
IF it is AcceptCondition, then render the normal signup view.
AcceptCondition GET renders the AcceptCondition view
AcceptCondition POST does RedirectToAction("SIGNUP")
Signup POST creates the user (Assuming) then goes?
Sounds like the referrer check isn't right so /account/signup is rendered again?
Whats your code look like.
It appears that you are passing a parameter of 'returnUrl' in your first function, but reference it as 'ru' in both the function body and in your RedrectToAction call in the third function. Be sure you are staying consistent with your parameter names as this could be a cause of faulty logic and bad/not working redirects.
In MVC 3-ASP.NET, I am validating the permission level on the page in the controller. If the user is authorised to see the page then I am using the following code to render it but I don't how to redirect to a new view if not authorised
Could any one tell me how to display alert saying, you are not authorised to see the page and redirect to home page?
public ActionResult viewName()
if(userAuthorised)
{
return View()
}
else
{
//Alert Message
//Redirect to different view like Home Page..
}
Any examples please?
Thank you
You have 2 choices.
1) Create a standard error view and return this in the else:
else
{
ErrorModel viewModel = new ErrorModel(){Msg="Error"});
return View("Error", viewModel);
}
2) Use a Redirect to Action which points at another Controller method which returns the Error View
else
{
return RedirectToAction("BadUser");
}
public ViewResult BadUser()
{
ErrorModel viewModel = new ErrorModel(){Msg="Error"});
return View("Error", viewModel);
}
See Controller.RedirectToAction Method
http://msdn.microsoft.com/ja-jp/library/system.web.mvc.controller.redirecttoaction.aspx