Return view from another post - c#

This is my code:
[HttpPost]
public ActionResult Edit(int id)
{
var viewModel = service.GetUserViewModel(id);
return View(viewModel); // reponse the ValidateLogin view
}
[HttpPost]
public ActionResult EditDetails(UserDetails userDetails)
{
return Edit(userDetails.Id);
}
Unfortunelly it is not returning view, but it is giving me error. What's wrong there?

You cannot return view from another action marked with [HttpPost] by using return Edit(userDetails.Id), instead it's necessary to set one action as [HttpGet] (i.e. Edit action method) and use RedirectToAction() overload which has route value parameter to call that action like example below:
[HttpPost]
public ActionResult EditDetails(UserDetails userDetails)
{
// note: the second overload is routeValues
return RedirectToAction("Edit", userDetails.Id);
}
[HttpGet]
public ActionResult Edit(int id)
{
var viewModel = service.GetUserViewModel(id);
return View(viewModel); // reponse the ValidateLogin view
}

Related

ASP.NET MVC - Cannot redirect to Create action

I've had a look around at the other questions related to redirecting to views, and none seem to fix my issue. I have a intermediary step to get to my Create action, and I cannot seem to redirect from that step's view to the Create view. An approximation of my actual code is:
public ActionResult SelectDependancy()
{
ViewBag.ProductID = new SelectList(db.Products, "ID", "Name");
ViewBag.ComponentID = new SelectList(db.Components, "ID", "Name");
return View();
}
The view for this action has a POST method that results in a call to SelectDependancy(string, string).
This POST is a standard POST and not an js AJAX POST
[HttpPost]
[ValidateAntiForgeryToken]
public void SelectDependancy(string ProductID, string ComponentID)
{
FilteredCreate(ProductID, ComponentID);
}
private ActionResult FilteredCreate(string ProductID, string ComponentID)
{
//Filter values based on ProductID + ComponentID
return RedirectToAction("Create");
}
The return RedirectToAction("Create"); doesn't seem to work. I have also tried changing it to return View("Create") (changing the return type of the method as well)
You must return ActionResult from SelectDependancy in order to redirect.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult SelectDependancy(string ProductID, string ComponentID)
{
return FilteredCreate(ProductID, ComponentID);
}

Use Get And Post in the same Controller

I want to use the HttpGet and HttpPost attributes for one action method. However, I have only seen examples where the attributes are used individually on separate action methods.
For example:
public ActionResult Index()
{
//Code...
return View();
}
[HttpPost]
public ActionResult Index(FormCollection form)
{
//Code...
return View();
}
I want to have something like this:
[HttpGet][HttpPost]
public ActionResult Index(FormCollection form)
{
//Code...
return View();
}
I remember having seen this done somewhere, but cannot remember where.
If you really want to do that, you can use the [AcceptVerbs] attribute. (See this SO question)
This way your method can handle the GET and POST verbs (but not others like PUT)
[AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)]
public ActionResult Index(FormCollection form)
{
//Code...
return View();
}
If you want your method to handle all verbs, donĀ“t use any attribute at all:
public ActionResult Index(FormCollection form)
{
//Code...
return View();
}

RedirectToAction from inside [HttpPost] to [HttpGet] - parameters

Code below:
[HttpGet]
public ActionResult Edit(string id="")
{
// ...
}
[HttpPost]
public ActionResult Edit(string itemId="", EditViewModel viewModel)
{
// ...
RedirectToAction("Edit", new { id = itemId });
}
returns an error: "Optional parameters must appear after all required parameters".
I assume it's trying to redirect to [HttpPost] action.
How to redirect to [HttpGet] action?
I'm trying to implement Save functionality where it will save the edit and reload the form with new values.
Error message is clear...
... if you know that an optional parameter is a parameter with a default value (empty string in your case)
[HttpPost]
public ActionResult Edit(EditViewModel viewModel, string itemId="")
{
// ...
RedirectToAction("Edit", new { id = itemId });
}
and you're done

GET and POST methods with the same Action name in the same Controller [duplicate]

This question already has answers here:
MVC [HttpPost/HttpGet] for Action
(4 answers)
Closed 2 years ago.
Why is this incorrect?
{
public class HomeController : Controller
{
[HttpGet]
public ActionResult Index()
{
Some Code--Some Code---Some Code
return View();
}
[HttpPost]
public ActionResult Index()
{
Some Code--Some Code---Some Code
return View();
}
}
How can I have a controlller thas answer one thing when is "getted" and one when is "posted"?
Since you cannot have two methods with the same name and signature you have to use the ActionName attribute:
[HttpGet]
public ActionResult Index()
{
// your code
return View();
}
[HttpPost]
[ActionName("Index")]
public ActionResult IndexPost()
{
// your code
return View();
}
Also see "How a Method Becomes An Action"
While ASP.NET MVC will allow you to have two actions with the same name, .NET won't allow you to have two methods with the same signature - i.e. the same name and parameters.
You will need to name the methods differently use the ActionName attribute to tell ASP.NET MVC that they're actually the same action.
That said, if you're talking about a GET and a POST, this problem will likely go away, as the POST action will take more parameters than the GET and therefore be distinguishable.
So, you need either:
[HttpGet]
public ActionResult ActionName() {...}
[HttpPost, ActionName("ActionName")]
public ActionResult ActionNamePost() {...}
Or,
[HttpGet]
public ActionResult ActionName() {...}
[HttpPost]
public ActionResult ActionName(string aParameter) {...}
I like to accept a form post for my POST actions, even if I don't need it. For me it just feels like the right thing to do as you're supposedly posting something.
public class HomeController : Controller
{
public ActionResult Index()
{
//Code...
return View();
}
[HttpPost]
public ActionResult Index(FormCollection form)
{
//Code...
return View();
}
}
To answer your specific question, you cannot have two methods with the same name and the same arguments in a single class; using the HttpGet and HttpPost attributes doesn't distinguish the methods.
To address this, I'd typically include the view model for the form you're posting:
public class HomeController : Controller
{
[HttpGet]
public ActionResult Index()
{
Some Code--Some Code---Some Code
return View();
}
[HttpPost]
public ActionResult Index(formViewModel model)
{
do work on model --
return View();
}
}
You received the good answer to this question, but I want to add my two cents. You could use one method and process requests according to request type:
public ActionResult Index()
{
if("GET"==this.HttpContext.Request.RequestType)
{
Some Code--Some Code---Some Code for GET
}
else if("POST"==this.HttpContext.Request.RequestType)
{
Some Code--Some Code---Some Code for POST
}
else
{
//exception
}
return View();
}
Can not multi action same name and same parameter
[HttpGet]
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(int id)
{
return View();
}
althought int id is not used
You can't have multiple actions with the same name. You could add a parameter to one method and that would be valid. For example:
public ActionResult Index(int i)
{
Some Code--Some Code---Some Code
return View();
}
There are a few ways to do to have actions that differ only by request verb. My favorite and, I think, the easiest to implement is to use the AttributeRouting package. Once installed simply add an attribute to your method as follows:
[GET("Resources")]
public ActionResult Index()
{
return View();
}
[POST("Resources")]
public ActionResult Create()
{
return RedirectToAction("Index");
}
In the above example the methods have different names but the action name in both cases is "Resources". The only difference is the request verb.
The package can be installed using NuGet like this:
PM> Install-Package AttributeRouting
If you don't want the dependency on the AttributeRouting packages you could do this by writing a custom action selector attribute.
Today I was checking some resources about the same question and I got an example very interesting.
It is possible to call the same method by GET and POST protocol, but you need to overload the parameters like that:
#using (Ajax.BeginForm("Index", "MyController", ajaxOptions, new { #id = "form-consulta" }))
{
//code
}
The action:
[ActionName("Index")]
public async Task<ActionResult> IndexAsync(MyModel model)
{
//code
}
By default a method without explicit protocol is GET, but in that case there is a declared parameter which allows the method works like a POST.
When GET is executed the parameter does not matter, but when POST is executed the parameter is required on your request.

Why is this URL like this in MVC3?

I was under the impression that every View in your application has it's own unique URL. For example:
Home/Index
Home/Test
Home/Error
Home/Help
In my Upload controller I call on the Error view. Yet the URL stays on what it was before, not changing to reflect the error url.
[HttpPost]
public ActionResult Index(HttpPostedFileBase excelFile)
{
if (excelFile != null)
{
*Snip for brevity, everything is peachy here.*
return View();
}
else
{
return View("Error");
}
}
Any suggestions why this is the case?
Shouldn't the URL be /Upload/Error? Thank you for your help. :)
URLs do not map to Views.
URLs map to Controller actions.
See this http://weblogs.asp.net/scottgu/archive/2007/12/03/asp-net-mvc-framework-part-2-url-routing.aspx
If you want a URL of /Upload/Error
You could make:
public ActionResult Error()
{
return View();
}
[HttpPost]
public ActionResult Index(HttpPostedFileBase excelFile)
{
if (excelFile != null)
{
*Snip for brevity, everything is peachy here.*
return View();
}
else
{
return RedirectToAction("Error","Upload");
}
}
You are returning the content of the View. If you want the URL to change, you need to RedirectToAction()
If you want the URL to change to /Upload/Error, here's what you would add to your UploadController:
public ActionResult Error()
{
return View();
}
Then, instead of returning the Error view, you would call: return RedirectToAction("Error","Upload");.
This basically shows the difference between controllers, actions, and views - controller actions can return any view they want (or other ActionResult) to a request, but only on one URL, unless they "reroute" the request to another action.
In ASP.NET MVC every URL maps to a controller/action. So you can return whatever view from your controller action, this doesn't change the URL.
If you want to redirect to an error Page, then either include a ErrorController in your project or an Error action in your FileUploadController and then do a Redirect to the appropriate action:
public class ErrorController : Controller
{
public ActionResult FileUploadError()
{
return View(); //returns view "FileUploadError"
}
}
public class FileUploadController : Controller // the controller you use to upload your files
{
public ActionResult Error()
{
return View(); //return view "Error"
}
public ActionResult Index(HttpPostedFileBase excelFile) // action from your post
{
//... do the upload stuff
else
{
return RedirectToAction("Error"); // if you want to use the Error action in this controller;
// or
return RedirectToAction("FileUploadError", "Error"); // if you want to use the action on the ErrorController
}
}
}

Categories