MVC4如何从一个控制器发布到另一个控制器

时间:2013-12-24 16:25:43

标签: c# asp.net-mvc asp.net-mvc-4

我可以使用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

3 个答案:

答案 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。

在您的情况下,您可以使用辅助方法获取控制器操作的内容,并从这两个操作中调用该方法。

这样,您可以在每个操作中保留HTTPPostValidateAntiForgeryToken个属性。