RedirectToAction is not redirecting at all - asp.net-mvc

i'm using RedirectToAction to redirect after a post to another controller and it's working. so i tried to Redirect to another action in the same controller and it's NOT working too.
public ActionResult finalize(int id)
{
Meeting meeting = db.Meetings.Find(id);
meeting.meetingStatus = "finalized";
db.SaveChanges();
return RedirectToAction("Index");
}
public ActionResult Create()
{
return View();
}
[HttpPost]
public ActionResult Create(Meeting meeting)
{
if (ModelState.IsValid)
{
db.Meetings.Add(meeting);
db.SaveChanges();
// return RedirectToAction("Invitation");
return (RedirectToAction("finalize", new { id = meeting.meetingID}));
}
return View(meeting);
}

you cant make 2 redirects in the same call , a redirect just return an http redirect code to another page , redirecting 2 times just wont work, don't treat action methods like normal methods they are different
for example when you request a page example.com/controller/action
action will be executed and for example it has a return value with RedirectToAction("NotFound")
what will happen in this scenario is
action body will be executed and the return value will send to the client an http header of 302 that says your new destination is /controller/NotFound
so RedirectToAction just return an http code to the client its not calling another method
Update
i was wrong i checked with fiddler2 , you can use redirect to action many times , what will happen the server will send multiple http redirect headers for each one
i jumped to conclusion this fast because i didnt think multiple redirect is the right way to do it, so after i tried it , i can say it works , just create a new project to see where is the problem exactly or use a tool like fiddler2

Related

Why is my routing prefix not working?

In my browser's address bar, I've got the following input:
http://localhost:55105/Tasks/UpdateStatus/8/1
However, it is not hitting my controller method when I debug.
[Route("Tasks/UpdateStatus/{id}/{status}")]
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult UpdateStatus(int id, int status)
{
Task task = db.Tasks.Find(id);
if (ModelState.IsValid)
{
task.Status = status;
db.Entry(task).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(task);
}
Getting following error:
Server Error in '/' Application. The resource cannot be found.
Your action method expects the parameters to be passed as POST and the via the way you are doing in the browser url it is get request as parameters are part of url as query string. What you need is a form in your view and post the values via form.
Make sure that you are sending the data as post method for you request.
For just to understand you can try renaming the [HttpPost] to [HttpGet] and see it will work, but that's not the way for the above use case as you are updating data in database so you should be using POST not GET

RedirectToAction after successful post to show a message

When people register on my ASP.NET MVC website I send an activation link via email so they can activate their account and login. I want to show a message when the registration is successful and the email is sent. To do that I redirect to another page.
I do not want to show this page when people go directly to this URL because it is not a normal page. I use TempData to check if they are coming from the registration page.
public ActionResult Register()
{
AccountRegisterView accountView = InitializeAccountRegisterViewWithIssue(false, "");
return View(accountView);
}
[HttpPost]
public ActionResult Register(AccountRegisterView accountView)
{
if (!ModelState.IsValid)
{
return View(accountView);
}
// Register user and send activation link via email...
TempData["success"] = true;
return RedirectToAction("RegisterEmail");
}
public ActionResult RegisterEmail()
{
if (TempData["success"] != null)
{
return View();
}
return RedirectToAction("Login");
}
I would like to know if this is considered best practice. Or should I do this differently?
I think this is a perfectly good use of TempData[]. You need a variable for a one time request to decide if you should show the page or not.
I suppose you could use a session variable, but you would need to remember to clear the session. You could use some type of registration key, but then you would need to track those as well. Long story short, nope, you are good.

TempData & Redirect for Errors

I have a controller action in my project that has a situation where it needs to display an error message to the user under certain scenarios. This action occurs in a POST:
[HttpPost]
public ActionResult DoSomeAction() {
if( someCondition )
return RedirectToAction("SomeActionError");
return RedirectToAction("Index");
}
public ActionResult SomeActionError() {
return View();
}
Currently I have it set up so that it will redirect to an error controller action. I'm not really fond of this approach because in the URL they see /SomeActionError and it also means that the user can directly navigate to this URL.
Is it a bad design/approach to put some flag in TempData and redirect to another controller that checks for the TempData error flag?
Example:
[HttpPost]
public ActionResult DoSomeAction() {
if( someCondition ) {
TempData["DoSomeActionError"] = true;
}
return RedirectToAction("Index");
}
public ActionResult Index() {
// check for error
if( TempData["DoSomeActionError"] ) {
return View("SomeActionError");
}
}
Is this a bad idea? Is there another approach that does something similar (doesn't allow the user to directly navigate to the error action)? I don't want to return the View on the POST action because I don't want them to refresh and cause another POST.
TempData is not per se a bad concept. TempData is for transporting an information to some consumer that reads that information and the information should vanish after it's been read.
The way your're using TempData is odd. A more elegant implementation for your requirements (you should show an error message) is to implement an equivalent to the rails flash concept and don't redirect to an error page but display an error message in your index view. Something like a red banner that says "The record could not be saved".
This question shows a nice flash implementation including the view stuff (not the accepted answer but the answer by #jim)
using tempdata in mvc is not a good approach.
If i were you i'll do as following:
[HttpPost]
public ActionResult DoSomeAction() {
if( someCondition ) {
return RedirectToAction("Index", new{error=true}
}
return RedirectToAction("Index");
}
public ActionResult Index(bool? error) {
// check for error
if(error?? false ) {
return View("SomeActionError");
}
}
While I don't agree TempData is always bad (I find it great for status messages I absolutely don't want passed on the url such as "record saved", I think in your case there may be a better option.
First you don't want an error page to be accessible - may I ask why?
To do a redirect when an error happens only to redirect again is a bit odd. I would throw the exception and handle that exception by your error view. MVC automatically adds the [HandleError] attribute as a global filter, so throw your exception (a custom type if necessary) and handle it in your error page as you see fit since you can access exception details there and it doesn't require a redirect.

asp.net mvc, wrong function being fired. - EDITED

I have master page that has this control that accepts Post verb. My LogOn page is also tied to the master page. When I enter wrong username/password, method of that control that accepts verb also gets fired along with the method to accept username password.
This is on HomeConroller:
[ActionName("ControlTemp"), AcceptVerbs(HttpVerbs.Post)]
public ActionResult ControlTemp(TempClass temp)
{
return PartialView("ControlTemp");
}
This is on AccountController:
[AcceptVerbs(HttpVerbs.Post)]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings",
Justification = "Needs to take same parameter type as Controller.Redirect()")]
public ActionResult LogOn(string userName, string password, bool rememberMe, string returnUrl)
{
if (!ValidateLogOn(userName, password))
{
return View();
}
FormsAuth.SignIn(userName, rememberMe);
if (!String.IsNullOrEmpty(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
Now, why do you think things are being posted to ControlTemp too?
EDIT: This is how I am referring to ControlTemp control on masterpage.
<div id = "divControlTemp"> <% Html.RenderAction("ControlTemp", "Home"); %></div>
So after watching debugger, I saw it returns View() if username/password is invalid. It then hits the divControlTemp control, but instead of firing
public ActionResult ControlTemp(), it fires
[ActionName("ControlTemp"), AcceptVerbs(HttpVerbs.Post)]
public ActionResult ControlTemp(TempClass temp)
and that is all I can see from the debugger. So my question is why do you think it thinks it is a post? Is it because the reurn View() was called from a method that was accepting Post verb?
If your question is "can a single http requests fire two separate action methods", the answer is no. Unless of course there is a redirect from one action method to the other or one of the methods calls the other directly. If there are redirections, you can see them in the Firebug console.
But frankly, if this was my software, I'd simply fire up the debugger and see what's going wrong. It shouldn't be too difficult to spot the problem this way.

What is the MVC way of simultaneously sending a file and redirecting to a new page?

I have a form which users must fill out and submit. The controller action does some work and decides the user can have a file and so redirects to another action which is a FilePathResult.
[CaptchaValidator]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(FormCollection collection)
{
// do some stuff ...
return RedirectToAction("Download");
}
[AcceptVerbs(HttpVerbs.Get)]
public FilePathResult Download()
{
var fileName = "c:\foo.exe";
return File(fileName, "application/octet-stream", "installer.exe");
}
What I would like to do is redirect the user to another page which thanks the user for downloading the file but I'm not sure how to accomplish that in a "MVC-like" way.
The only way I can think of off the top of my head is to skip the Download action and instead redirect to the ThankYou action, and have the ThankYou view use javascript to send the file. But this just doesn't seem very MVC to me. Is there a better approach?
Results:
The accepted answer is correct enough but I wanted to show I implemented it.
The Index action changes where it redirects to:
return RedirectToAction("Thankyou");
I added this controller (and view) to show the user any "post download information" and to say thanks for downloading the file. The AutoRefresh attribute I grabbed from link text which shows some other excellent uses.
[AutoRefresh(ControllerName="Download", ActionName="GetFile", DurationInSeconds=3)]
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Thankyou()
{
return View();
}
The action which get redirected to is this same as it was before:
[AcceptVerbs(HttpVerbs.Get)]
public FilePathResult GetFile()
{
var fileName = "c:\foo.exe";
return File(fileName, "application/octet-stream", "installer.exe");
}
Just add a header to your response, in the action for your redirected page.
Googling came up with this header:
Refresh: 5; URL=http://host/path
In your case the URL would be replaced with the URL to your download action
As the page I was reading says, the number 5 is the number of seconds to wait before "refreshing" to the url.
With the file being a download, it shouldn't move you off your nice redirect page :)

Resources