asp.net mvc: pass information between 2 controllers to the view - asp.net-mvc

hope i can explain myself...
i have a login control in the masterpage. when you click the login button you go to the accountcontroller's logon method which checks your credentials. whether it is ok or not, you will be redirected to the homepage with a redirecttoaction("home","index").
but, in case login failed, i want to show a message to the user.
so what i tried was setting viewdata in the logon method (viewdata["logon"] = "failed") and then check in the masterpage if this viewdata was present and if so, render a span with some text.
but as i understand the viewdata is not preserved with the redirect to action method.
what is the best way to make sure my logon method can somehow notify my masterpage view that login failed?
Michel

If I read your question correctly your problem is that you need to set a value in your action that need to be available after RedirectToAction. You would need to set a key in Tempdata.
TempData["MessageToUser"] = "I dont let you in dude!"
TempData is still available after one redirect.

Check out MvcContrib. Queen3 somewhere mentioned that they have cure for this
(passing information between redirects).
But it would be better to create separate view for authentication. Then problem would just disappear.

Related

MVC passing values through several views

I have a login view for a user to authenticate: after he inserts his username and password, the next view has a section with welcome, username message. I pass this information through a ViewBag.welcomeMsg and everything is smooth.
When I advance to another view, that section no longer contains the message as the ViewBag.welcomeMsg is defined in the first login controller and gets erased after that.
I don't want write in every controller ViewBag.welcomeMsg = "...";
My question: is there a way to pass a variable like ViewBag that persists and can be accessed from every view of the web application? Like a static field?
If you just want to show the welcome message on your view when user is authenticated then just modify your view like this :
#if (Request.IsAuthenticated)
{
<text>Welcome, #User.Identity.Name</text>
}
Can check with the TempData which will be available till start of the next view rendering. so that you can set it to the other viewbag from tempData.
It very much depends on how you handle the authentication process. If you are using FormsAuthentication for example, then the user information will be stored in User.Identity.Name. You can access User property from various contexts like controller, view, etc.
On the other hand if you are handling the authentication by yourself, my suggestion to you would be to do any of the following (I am writing this from top of my mind, so if I miss a name of a property, forgive me):
Store username in a cookie, and in Global.asax handle PostAuthenticated event where you will read the username (if authenticated) from the cookie. After that create a GenericPrincipal object with GenericIdentiy and assign it to a Controller.User
Store the information in a session (the easiest of all) and pass it around. However, the problem with this is if you have a sessionless controller in which case you cannot rely on this approach.
I wrote an article a long time ago about working with roles and principals, but you can get a picture on how to handle your problem with this solution http://mvcdeveloper.wordpress.com/2013/06/08/passing-user-roles-to-httpcontext-user/

How do I implement a logon HTML form as part of my master layout?

I have a requirement to include logon fields in my right column of a 3 column layout, with the body view being the centre. Right now I simply have Logon actions in my home controller, but IN haven't given this much work yet and am running into difficulties. I use a partial view for the HTML form with login fields, but I want to move the logon actions into my Account controller. However, my quandary is how to. so to say, return a partial view from an action method, e.g. for a bad logon message.
For that purpose, Html.RenderAction is used. Simple way to inject output of other menu, logon, etc. actions into generated html
Do you use AJAX or you submit the form back?
I would suggest using AJAX to send the form data. If the login is unsuccessful you can return some string or whatever message you like (you can also return the partial view), if it is successful you can authenticate the user and redirect to home page.

What's the Rails way to temporary branch to a different controller's action?

In my Rails controller I want to branch to a different controller's action, show its view and then return back to my original action, i.e. it's not a simple redirect, more like a sub-procedure call.
I want to use this whenever a user does something suspicious, like editing a post too often in a row. I still want to allow the edit, but first the user has to answer some CAPTCHA-like questions on a different page. (Similar to Authlogic-oid, where during validation the user is redirected to the OpenID provider's page)
You can push the current request into the Session, then do a redirect to the captcha, then have the captcha action look into the Session to check where it should redirect to.
IIRC, Autlogic does exactly that with redirect_back_or_default.
You can't.
Convert the common stuff into a helper method and then both the controllers should call this method.
It's possible to create an instance of the other controller and call methods on it, but you should probably reevaluate your organization first (look into helpers, modules, etc.)
#my_other_controller = MyOtherController.new
#my_other_controller.some_method(params[:id])

Why are Redirect Results not allowed in Child Actions in Asp.net MVC 2

I have some partial actions that I render with the Asp.Net Futures RenderAction method. Some of these perform redirects after the forms in them have been processed.
Now that I upgraded to Asp.Net MVC 2 RC it gives me an error "Child actions are not allowed to perform redirect actions".
I checked out the source code and I found the line that throws the exception. To Get around it I can make a custom RedirectResult, But before I do I want to understand why the framework doesn't allow it in the first place. There must be a good reason and maybe I Shouldn't do either.
Any one know the reason for this limitation?
Thanks
The limitation exists because MVC has already started rendering a view to the client. The effect of redirecting from this point is undefined. It could work perfectly, it could continue rendering the original view without redirecting, it could throw a different exception, etc.
Since the result of performing this action is undefined, the framework blocks it. In practice, RenderAction should never be used to render anything other than a view (or view-like content) for similar reasons.
In your particular case, the outer action should redirect. If you're just going to end up redirecting from within the view anyway without showing anything to the user, then there was really no purpose to going through the view in the first place, as the outer action could have delegated the work appropriately on its own.
Try to use something like this in Child Action:
ControllerContext.HttpContext.Response.Redirect(ControllerContext.HttpContext.Request.Url.ToString());
My solution.
Action method:
return View("Redirect", model);
View:
<script type="text/javascript" language="javascript">
document.location = '<%: Url.Action("Index", "Album", new { id = Model.Id }) %>';</script>
In my case, the form being rendered is a "configure" panel on an extension to a website I'm building. I'd like the extension's own controller to be able to handle the form processing and then redirect back to the admin page listing all configured extensions. I don't think it's appropriate or practical here to ask the parent page's controller to process the form for the extension. What would you suggest I do instead?
In my unusual case, I had a custom AuthorizeAttribute attached to my controllers which was attempting to redirect on a child action, which is (as mentioned above) not allowed.
To resolve the issue, I removed authorisation checking redirection on all child actions:
Public Overrides Sub OnAuthorization(filterContext As AuthorizationContext)
//Child actions cannot redirect anyway, so no need to check permissions.
If filterContext.IsChildAction Then Exit Sub
.. parent authorisation checks ..
Sometimes this error occured when you try to render an action of base action result.
Example:
ActionResult X
Return View
View X
RenderAction Y
ActionResult Y
// Bla bla
return View
// else
return RedirectToAction X
In that case just point the partial view form's submit url to action that was the target of your problematic redirection and let it perform itself redirection to its GET version.

Post/Redirect/Get: Redirect to specific route

I have the following scenario:
I have an edit page, which can be called from different pages. These pages could be the detail view for the current entity, or the list view for the entities (with or without a search in the route).
HOW do I cleanly redirect to the original calling page using the MVC framework? Of course I could simply pass the HttpContext.Request.Url value by holding it in my TempData, but that sort of smells, in my eyes (or, err, nose). It's on a lower level than the rest of the code.
Is there a way to get the routevalues for the previous page in a controller context? If I have that, I could store that temporarily and pass that to the redirect.
Do not use TempData when not redirecting. One AJAX request from your edit page, and the TempData will go away.
Tomas is right that a hidden element or query string parameter is the way to go. But make sure you sanitize the value submitted. You don't want to redirect any old site on the web; you need to ensure that the page to which you redirect is part of your sites.
you can always have a hidden form element telling the controller where to redirect when posting a form. when using a get request, you could use a querystring in a similar way. it might not be the most beautiful solution, but it's quite a lot safer than trusting httpreferrer or other headers that could easily be changed (or ommitted) by the browser.

Resources