我可以使用Get和RedirectToAction来做到这一点,但我想知道为什么我不能使用Post? 我在Subscriber控制器中,想要从CreateTest控制器返回一个视图。 当它返回时,它假定我仍然在Subscriber中并且不查看Controller视图。
public class SubscriberController : Controller
{
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CreateTestPortal()
{
CreateTestController ctc = new CreateTestController();
return ctc.CreateTestPortal();
}
}
public class CreateTestController : Controller
{
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CreateTestPortal()
{
//... validation logic
var vm = new CBT.Models.CreateTest.CreateTestPortal();
//... build form logic
return View(vm);
}
}
如果我从Subscriber中的CreateTestPortal进行此调用,
return RedirectToAction("CreateTestPortal", "CreateTest");
它正确返回表单,但我必须使用GET方法并失去ValidateAntiForgeryToken的安全性。这是默认行为还是我错过了一步。
我正在使用MVC4
答案 0 :(得分:3)
我会在这里走出困境,因为你可能不知道你可以 POST
到另一个控制器,但它发生在视图中,而不是来自行动。
Html.BeginForm()
有几个重载可让您完全控制要将表单提交到哪个控制器/操作。假设这是FirstController/Index
的视图:
@using (Html.BeginForm("SomeAction", "SecondController", FormMethod.Post))
{
@Html.AntiForgeryToken()
// rest of form
}
SecondController
可能如下所示:
public class SecondController : Controller
{
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult SomeAction(SomeModel model)
{
if (ModelState.IsValid)
{
// Add to database, or whatever, and now redirect
return RedirectToAction("Success");
}
// Redisplay the form if validation failed.
return View(model);
}
}
答案 1 :(得分:2)
你做错了!你不应该像这样创建控制器。控制器不应该像这样使用。如果你有一个逻辑对两个操作都做同样的事情 - 将它提取到服务类或命令处理程序中,并使用来自两个控制器的那个类。
这可能看起来像是一项额外的工作,但请相信我,这对于可维护性是值得的。
了解MVC的一条规则 - 一个控制器操作,用于应用程序中的一个逻辑操作。如果您尝试为每个控制器操作分配多个逻辑操作 - 事情会变得很脏并且很快。你最终会得到意大利面条代码。
很多时候,似乎行为正在做同样的事情,你试图将它重构为常用方法。但通常这似乎只是类似的行为。实际上,重复的动作不应该存在,或者2个动作正在做不同的事情,只是看起来很相似。
回答你的直接问题 - 不要做你正在做的事情。停下来,思考和重构,这样你就不需要做这些黑客了。
UPDATE:并且您无法导航到其他控制器的POST操作是正确的。 POST操作用于表单提交。用户使用防伪令牌提交表单,然后转到POST操作。如果要重定向用户,则需要执行以下操作:
public class HomeController : Controller
{
public ActionResult Blah(int someParam)
{
// do something
return RedirectToAction("SomeOtherAction", "SomeOther");
}
}
public class SomeOtherController : Controller
{
public ActionResult SomeOtherAction()
{
// and do something here
return View();
}
}
答案 2 :(得分:0)
如果您正在调用另一个控制器操作或重定向,则无法使用HTTPPost属性。当您发布时,这是从用户完成的,您使用重定向或调用操作不是发布。当你有一个用HttpPost修饰的动作,并用GET调用它时,它会显示一个错误,好像该对象不存在一样。为了完成这项工作,你应该在你的服务器上制作一个帖子请求...这有点像hacky。
在您的情况下,您可以使用辅助方法获取控制器操作的内容,并从这两个操作中调用该方法。
这样,您可以在每个操作中保留HTTPPost
和ValidateAntiForgeryToken
个属性。