How to pass Return URL in MVC3? - asp.net-mvc-3

I have the following LogOn Action
[HttpPost]
public ActionResult LogOn(LogOnModel user, string returnUrl)
{
if (!String.IsNullOrEmpty(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
In which My returnUrl is null..
Can any body tell me .Why my return URL is null

I wrote up a very fix fix to this. Basically add a route value needs to be added to the Html.BeginForm as follows.
Html.BeginForm("LogOn",
"Account",
new { returnUrl = Request.QueryString["ReturnUrl"] })
For more details see http://blog.nicholasrogoff.com/2013/12/10/net-mvc-3-logon-does-not-redirect-out-the-boxquick-fix/

That's depends how you call the controller action method.
If you have an URL like below
http://www.somedomain.com/LogOn/LogOn?returnUrl=user/userList
In this call, your returnUrl parameter of an ActionMethod (LogOn will be replaced by querystring parameter returnUrl.
If you're using form authentication, there is an [Authorize] attribute which validated the authentication. If user is NOT authenticated, then it will redirect to the LogIn page with the querystring parameter returnUrl which will have a requested page url in it.
At this moment, you will also get returnUrl value in controller's action method parameter with returnUrl paramter with value which will have requested page Url
Hope this helps!

It depends on who is calling this method and whether this parameter is supplied in the POST request.
For example if the user tries to access a controller action decorated with the [Autorize] attribute and he is not authenticated the framework will automatically redirect to the LogOn action (the one that renders the form, not the one with [HttpPost]) and supply the returnUrl parameter.
Then you could have a hidden field in the logon form to persist its value so that when the user enters his credentials and submits the form to the LogOn action, in case of successful login, he is redirected to the initially requested page.

Related

Stoping users from accessing an ActionResult but allow it to be acessed via Html.Action/RenderPartial code and AJAX calls

I have some ActionResults that I don't want an user to be able to directly access but I need to be able to call them from views using #Html.Action, #Html.RenderPartial, and AJAX. I was using the ChildActionOnly but if I use that I can't access the page via AJAX. If I remove the ChildActionOnly attribute I can call it by AJAX but I can also call it directly by URL which is what I don't want happening. Is this possible to do of do I have to leave the ActionResult opened?
You can have the public action with a parameter to indicate whether or not the method should be executed like
public ActionResult DoSomething(bool shouldBeExecuted=false)
{
if (shouldBeExecuted == false)
{
throw new UnauthorizedAccessException("The action is not available");
}
ViewBag.Title = "Test Page";
return View();
}
And when you create a link for the action, just pass the "true" as a query string value.

What is ReturnURL in mvc3

What is Return URL in mvc3? When i write down my url in adress bar of the browser, at the append return url is automatically appended to it. How this happnes?
I provide the following url in adress bar
http://localhost:55875/admin
and after pressing enter it becomes
http://localhost:55875/Account/Logon?ReturnUrl=%2fadmin
I have debugged the logic for Logon action method, but dont see any logi which is appending returnurl to the provided url? How did this happen?
When an unauthenticated user tries to get into a section of your application which requires authentication, then returnUrl comes into the picture.The Url requested by the unauthenticated user is basically stored in returnurl.
for example below controller decorated with Authorize attribute :
[Authorize]
public ActionResult Login(string returnUrl)
{
ViewBag.ReturnUrl = returnUrl;
return View();
}
The login action grabs the value of this parameter and puts it in the ViewBag so it can be passed to the View.
The View then stores this value in the form as shown by this line of code in the View.
#using (Html.BeginForm(new { ReturnUrl = ViewBag.ReturnUrl }))
The reason it is stored in the View is so that when the user does a Submit after entering their user name and password, the controller action that handles the post back will have access to this value.
Your application must be having Authentication for login which is handled by [Authorize] attribue. as user is not authenticated it returns to logon page with returnurl as admin
For more on AuthorizeAttribute How to use authorize attribute on MVC3
Below is the standard action of login when you login above returnurl ie admin is passes as second parameter, depending on which user is redirected to the page using return Redirect(returnUrl);
[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
if (ModelState.IsValid)
{
if (Membership.ValidateUser(model.UserName, model.Password))
{
FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")
&& !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
{
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);
}
Routing is one of the core concept of any ASP.NET MVC application. A URL of a MVC application is the combination of your Application root URL followed by Controller name and then Action to which request has been made e.g.
http://localhost:55875/{controller}/{action}/{optional parameters}
You probably have chosen new project with Account Controller and Authorization membership providers. As fellow members has mentioned, the Authorize attribute is probably the main reason you are being redirected to logon page.
From the documentation of Authorize attribute:
If an unauthorized user tries to access a method that is marked with
the Authorize attribute, the MVC framework returns a 401 HTTP status
code. If the site is configured to use ASP.NET forms authentication,
the 401 status code causes the browser to redirect the user to the
login page.
In browsers, whenever you hit enter key in address bar, browser always make a GET request to the server for resources.
That is what could have happened. Either your Admin Controller or its Index() method is decorated with [Authorize] action filter attribute e.g.
public class AdminController : Controller
{
///<summary>
/// This view will open whenever you make a HTTP GET request to your Admin
/// controller without providing any action method name in request explicitly.
/// Because it is decorated with Authorize attribute, any user who has not logged in
/// will be redirected to the login page...
///</summary>
[Authorize]
public ActionResult Index()
{
return View();
}
}
You may wonder why did application redirected to login view?
This is because by default this action has been set in your application inside your web.config file.
<authentication mode="Forms">
<forms loginUrl="~/Account/Logon"/>
</authentication>
MVC leverages the power of built-in authentication logic and redirects the user to view that has been set under loginUrl.
Try removing the [Authorize] action filter just for a change and see what happens. In the end it is your business logic to decide on which views you need to have only authorize or anonymous access.
However, you may also take a look at AllowAnonymous attribute. It allows you to skip authorization for a perticular contoller or action.
[Authorize]
public class AdminController : Controller
{
///<summary>
/// Skips Authorization..
///</summary>
[AllowAnonymous]
public ActionResult Index()
{
return View();
}
///<summary>
/// Only allows authorize access...
///</summary>
public ActionResult Secure()
{
return View();
}
}
You can customize/override the behavior of these action filters as well.
Notice, [Authorize] has been added to controller itself if you have selected the project with internet and membership providers which will make all the actions inside this authorized except those with [AllowAnonymous] filter (if exists).
This article has good overview of Action filters in MVC.
First: you are trying to access an authorized page so every time you are trying to access this page the application automatically redirect you to login page
Second: how this happened?
in web.config file you can find a section for authentication
<authentication mode="Forms" >
<forms loginUrl="~/Account/Logon"/>
</authentication>
this section says that each time you are trying to access authorized page you will be redirected to this page and since its forms authentication so you will be redirected to this page
another thing you may using Authorize an AuthorizeAttribute which tells the application that the following ActionResult can't be accessed by anonymous users you can use this attribute in class level or ActionResult level as follows
[Authorize]
public class HomeController
{
}
Or
public class HomeController
{
[Authorize]
public ActionResult Index()
{
}
}

Avoiding unauthorized access to a page by changing the URL query parameter in mvc3

I'm new in mvc and I have a question: If I have Index page (page with list of some object this is url http://localhost:6384/admin/) and I have actionlink button on which when user clicks he gets details of that object this is url http://localhost:6384/Admin/Apartman/details/1.
ID of obejct is 1, but if user change value 1 to some other value he will get some other object which maybe he shouldn't be able to see it.
What can I do to protect application?
The way i do it is simply checking whether the user has access to that object.
public ActionResult EditProfile(int id)
{
ApartmentViewModel objVM=MyService.GetApartment(id);
if(objVM.CreatedById==id)
{
return View(objVM);
}
else
{
return View("UnAuthorized");
}
}

Submit button which RedirectToAction to previusly page.

I have one method which I use in some place. Now I make RedirectToActio.... and back me to the concrete page. Is possible to make, it back to previusly page?
You could use the Referer HTTP header but it's not very reliable. A better way is to pass the url you want to redirect to the controller action (it's the way the POST LogOn method on the AccountController is implemented when you create a new ASP.NET MVC 3 application using the built in wizard. Take a look at it):
public ActionResult Foo(string returnUrl)
{
...
return Redirect(returnUrl);
}
Then when you call this action you pass the url of the current page. For example you could generate the following anchor:
#Html.ActionLink(
"do some processing and redirect back here",
"foo",
new { returnurl = Request.Url.AbsoluteUri }
)

Need help with ReturnUrl in MVC 3 LoginPage

I have this url in my login view: http://localhost:5550/login?ReturnUrl=/forum/456&theme=1
I get the right url value when I am in the login page.
As you can see I have 2 query string parameters: ReturnUrl and theme
So far good.
Now the login page posts a form to a controller action.
All I need is to read the values of these 2 query string params.
I just can't make it work.
This is my login page view:
#using (Html.BeginForm("try", "login"))
{
//set text boxes and button so user can try login
}
This is my controller where I need those 2 values:
[HttpPost]
public ActionResult Try(LoginModel model, string ReturnUrl, string theme)
{
//read all query string param values...but how?
//I am not getting anything in string ReturnUrl, string theme. They are null
}
Other part of the question:
I can debug other controller. But not this controller.
Is this because I am posting a form using BeginForm?
Doesn't make sense. But the breakpoint never hits even though I get error on browser.
Normally you shouldn't be reading from ReturnUrl. The flow works like this:
Request to controller action which requires authentication using the [Authorize] attribute
ASP.NET MVC adds the ReturnUrl and redirects to /Account/LogOn, automatically encoding and appending the ReturnUrl parameter
The Account/LogOn POST controller action, after authenticating the login information, redirects to the URL in the ReturnUrl.
I wrote about that in gory detail in the following posts:
Looking at how the ASP.NET MVC Authorize interacts with ASP.NET Forms Authorization
Preventing Open Redirection Attacks in ASP.NET MVC
The second post indicates one good reason why need to be careful with ReturnUrl - users can tamper with them.
In the example you showed above, I'd expect that, after authorization, the user would be redirected to the Forum / Index action, which would then be reading the values. If you are creating the ReturnUrl, you should be URL Encoding the second &.
Not sure on the exact reason the values don't get bound, but the easy workaround is to add those properties to your login model and add hidden fields on the form.
Try changing the decoration:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Try(LoginModel model, string ReturnUrl, string theme)
{
//read all query string param values...but how?
//I am not getting anything in string ReturnUrl, string theme. They are null
}

Resources