New to MVC and having trouble trying to "Logout" of my site. I have a LogOn() method and view that comes up first to show the Log On page. After I log on then I go to a another page with a button to log out. (note: this is not likely directly related to logging in/out. that is just the story I'm working on)
<asp:Content runat="server" ContentPlaceHolderID="GlobalNavbarPrimary" ID="Content3">
Logout
</asp:Content>
When I press the button then it correctly finds my SignOut method. However, after I logout I try to run a redirect to go back to the LogOn action. I'm not understanding why my LogOn method is not run/found. Here are my LogOn methods and my SignOut method.
public ActionResult LogOn()
{
return View();
}
[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
if (ModelState.IsValid)
{
string sourceIp = string.Empty;
if (!string.IsNullOrEmpty(Request.UserHostAddress))
sourceIp = Request.UserHostAddress;
try
{
XX.User user = new XX.User();
XX.SessionKey sk = null;
sk = user.Logon(model.EmailAddress, model.Password, sourceIp);
Session[MyAuthorizeAttribute.MySessionKeyName] = sk.Value;
return RedirectToAction("Index", "Message");
}
catch (Exception ex)
{
ModelState.AddModelError(ex.Message, "Fatal Error");
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
public ActionResult SignOut()
{
CM.User user = new CM.User(Key);
user.Logout(Key);
// This does not go to the LogOn action!!!!!
return RedirectToAction("LogOn", "Account");
What is also troubling is that the address bar shows http://localhost:1159/#/Account/SignOut, whereas I was expecting to see http://localhost:1159/#/Account/LogOn (or ....//localhost:1159/)
Any insight (or suggestions for debugging strategies) would be most welcome.
I found that if I removed jQuery-mobile from my master page then it works as expected. I had seen some strange things, such as the source of the page (View Source) not matching what I was looking at (actually showing the source of a different page) - an impossibility, so I thought.
I'll have to look at jQuery-mobile closer. I know it is in beta, so perhaps I just hit a known issue.
Related
The following code snippet is from my ASP.NET MVC 5 application:
public ActionResult Ask(string id) {
if (!this.User.Identity.IsAuthenticated) {
string retUrl = Request.Url.AbsoluteUri;
return RedirectToAction("Login", "Account", new { returnUrl = retUrl });
}
...
}
The idea is, if the user has not yet logged in, he will be taken to the login page and subsequently be returned back to this "Ask" page.
When the user enters, for example, http://example.com/Home/Ask/12345678, method Ask() gets invoked with the correct value for id. The user is now redirected to the login page.
After Login() code in AccountController successfully authenticates the user, it calls ReturnToLocal(), passing in the url that we expect (http://example.com/Home/Ask/12345678). However, instead of invoking the Ask() method , ASP .NET somehow ends up invoking Index() method.
Appreciate your help in understanding why my redirection is broken. Regards.
Since you did not provide us neither the Login action method nor RedirectToLocal method I am assuming you are using the AccountController from MVC5 template.
If so
private ActionResult RedirectToLocal(string returnUrl)
{
if (Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
return RedirectToAction("Index", "Home");
}
You can see that RedirectToLocal method checkes if the returnUrl parameter is 'localUrl'.
If not it does invoke Index.
In your Ask method you are passing string retUrl = Request.Url.AbsoluteUri as returnUrl which is not local (starts with http://)!
Try string retUrl = Request.Url.PathAndQuery
I am trying to redirect to action and get a new view (a new page) with no success. While debugging, I'm reaching the controller but not getting the view (the page URL is not changed).
With Fiddler I see that the page returns the right view result but in the browser the URL is not changed!
When shopping cart is empty, I would like to redirect to a new page a display the error message.
[HttpPost]
public ActionResult PlaceOrder(DeliveryDetails deliveryDetails)
{
if (UserCart.IsEmpty)
{
TempData["errorMsg"] = "Error: Cart is empty";
return RedirectToAction("Index", "Error");
}
else
{
// do something..
}
}
ErrorController:
public ActionResult Index()
{
return View();
}
ErrorController View:
#TempData["errorMsg"]
Any suggestions on what is going on ?
It was a js problem:
event.isDefaultPrevented()
Is your 'ErrorController View:' should be named Index.cshtml? If it is not it should be.
I have a requirement to implement Back button functionality in MY MVC2 application(with explicit Back buttons in the application, not via browser back button).
I have gone through the link here Back button functionality using ASP.net MVC which advises to use Request.UrlReferrer. and it works well whenever I have a HTTP Get (as it comes up with querystring.) but I face issue when previous page was a HTTP POST with no querystring.
Has anyone worked on a solution like this?
We have initial thoughts of generating and storing links like Stack, and popping out urls one by one when user clicks on 'Back' button. But if there is a better solution\design pattern which helps me achieve that?
You could store the returnurl to actionresult routevalues and have a html helper for back link.
Helper:
public static class HtmlHelpersExtensions
{
public static MvcHtmlString BackLink(this HtmlHelper helper,string defaultAction)
{
string returnUrl = HttpContext.Current.Request["returnUrl"];
// If there's return url param redirect to there
if (!String.IsNullOrEmpty(returnUrl))
{
return new MvcHtmlString("<a href=" + returnUrl + " >Back</a>");
}
// if user just posted and there's no returnurl, redirect us to default
else if (HttpContext.Current.Request.HttpMethod == "POST")
{
return helper.ActionLink("Back", defaultAction);
}
// we didn't post anything so we can safely go back to previous url
return new MvcHtmlString("<a href=" + HttpContext.Current.Request.UrlReferrer.ToString() + " >Back</a>");
}
}
Controller:
public ActionResult MyAction(string returnUrl)
{
return View(new MyModel());
}
[HttpPost]
public ActionResult MyAction(MyModel mm, string returnUrl)
{
if (ModelState.IsValid)
{
// No returnurl, redirect us to somewhere
if (string.IsNullOrEmpty(returnUrl))
return RedirectToAction("Index");
// redirect back
return Redirect(returnUrl);
}
return View(mm);
}
Usage:
#Html.ActionLink("MyAction", "MyAction", new { returnUrl = Request.RawUrl.ToString() })
Backlink in MyAction.cshtml
#Html.BackLink("Index")
Now the helper decides whether it uses returnUrl param, default action or takes you back via urlreferrer.
When implementing an MVC web app with FormsAuthentication, it would appear that the FormsAuthentication mechanism automagically appends ?ReturnUrl=/ to your mvc routes. I did notice, though, that the default web application which MVC 3 provides out of the box implements FormsAuthentication but does not appear to suffer from the appended ReturnUrl=/ problem. I've looked through the code and can't see where this is being handled. Anyone know?
In the LogOn action of the AccountController, you'll see that if a return url is present, the user will be redirected to it after a successful log on:
[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
if (ModelState.IsValid)
{
if (MembershipService.ValidateUser(model.UserName, model.Password))
{
FormsService.SignIn(model.UserName, model.RememberMe);
if (Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
else
{
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
Try adding the [Authorize] attribute to the Action or controller. This will generate the url needed to redirect after login.
I am new to ASP.MVC. My background is in ASP.NET Web Forms, I think this is what is causing my confusion. I understand that the "M" basically represents the data source, the "V" represents the resource I'm requesting and the "C" dictates what gets shown to an end-user. But then I get confused.
For instance, I'm just trying to create a Login screen. I envision a user visiting "http://www.myapp.com/Account/Login" and they will be presented with a traditional Login screen. To accomplish this, I have added the following in the RegisterRoutes method in my Global.asax file:
routes.MapRoute(
"Login",
"{controller}/{action}",
new { controller = "Account", action = "Login", id = "" }
);
The Login action executes, but this is where I get confused. You see, the first time the login screen loads, I would expect to just show a username/password field. Then on post, I would expect the form to be validated and processed. In an attempt to do this, I have created the following method:
public ActionResult Login()
{
bool isFormValid = ValidateForm();
if (isFormValid)
LoginUser();
else
ShowErrors();
return View();
}
My confusion rests with the Login action. Initially, there is no data. But the next time, I want to validate the data. How do I determine if the Action is a postback or not?
Thank you!
The easiest way to handle this is with two actions: one for get, one for post. Use the AcceptVerbs attribute to control which gets invoked depending on the method. BTW, the default routes should work just fine for this case since when the controller and action is supplied it gets directed as you would expect. I thought that this scenario was also covered in the project template -- did you set up a project using the template or an empty one?
[AcceptVerbs( HttpVerbs.Get )]
public ActionResult Login()
{
}
[AcceptVerbs( HttpVerbs.Post )]
public ActionResult Login( string userName, string password )
{
}
You need two different methods, for Post and Get.
[AcceptVerbs (HttpVerbs.Get]
public ActionResult Login ()
{
return View ();
}
[AcceptVerbs (HttpVerbs.Post]
public ActionResult Login (FormCollection form)
{
if (AuthenticationSuccess ())
return RedirectToAction ("Account");
else
return View ();
}
For Post version you can use the model binding mechanism:
public ActionResult Login (LoginModel loginModel)
Or
public ActionResult Login (string LoginName, string Password)