在ASP .NET MVC中,控制器之间共享数据的最佳方法是什么?

3

我有两个控制器:


public class AController : Controller
{
      public ActionResult AControllerAction()
      {
          if (// BControllerAction reported an error somehow )
          {
                ModelState.AddModelError("error-key", "error-value");
          }
          ...
      }
}

public class BController : Controller
{
      public ActionResult BControllerAction()
      {
          try{Something();}
          catch(SomethingExceprion)
          {
              // here I need to add error info data,
              // pass it to AController and redirect to
              // AControllerAction where this error will be added 
              // to model state
          }
      }
}

我认为我可以做类似这样的事情:
public ActionResult BControllerAction()
{
     try{Something();}
     catch(SomethingException)
     {
         var controller = new AController();
         controller.ModelState.AddModelError("error-key", "error-value");
         controller.AControllerAction();
     }
}

但我认为这会是一种破坏架构的方法,我不想这样做。除了传递模型对象之外,是否有更简单、更安全的方式?


你的方法是正确的。 你可以执行另一个控制器并返回它的ActionResult。请参见这里 - semao
请参阅以下示例:.NET MVC - 从另一个控制器操作中调用控制器操作。如果您有两个控制器需要的逻辑,那么这个逻辑要么不属于控制器,要么属于共享基类控制器。 - CodeCaster
你是否使用ModelState来记录异常? - Forty-Two
@Forty-Two,如果出现异常,在日志记录器的catch(SomethingException)块中记录,我只需要通过另一个控制器的操作通知用户此错误。 - Dmytro
2个回答

3
根据您需要向控制器A传递的异常细节,我建议采取以下方式:
public ActionResult BControllerAction()
{
     try{Something();}
     catch(SomethingException ex)
     {
         return RedirectToAction("AControllerAction", "AController", new { errorMessage = ex.Message() })
     }
}

然后将被调用方法的签名更改为:

public ActionResult AControllerAction(string errorMessage)
      {
          if (!String.IsNullOrEmpty(errorMessage))
          {
                //do something with the message
          }
          ...
      }

2
您可以返回一个重定向到 AControllerAction。您可以使用 TempData 字典(类似于 ViewData)在此类调用之间共享数据(存储在这种方式下的数据将在同一会话的下一次请求中持久存在,如此博客文章所解释)。
示例:
public class AController : Controller
{
      public ActionResult AControllerAction()
      {
          if (TempData["BError"] != null)
          {
                ModelState.AddModelError("error-key", "error-value");
          }
          ...
      }
}

public class BController : Controller
{
      public ActionResult BControllerAction()
      {
          try{Something();}
          catch(SomethingExceprion)
          {
              TempData["BError"] = true;
              return RedircetToAction("AControllerAction", "AController");
          }
      }
}

TempData是ControllerBase类的属性,因此我只能通过这种方式在同一个控制器的操作之间传递数据,而不能在多个控制器之间传递数据。 - Dmytro
@DmytroTsiniavsky 刚刚仔细检查了我的最近一个项目。在不同的控制器中使用它似乎没有任何问题。 - yoozer8
虽然我必须承认,我喜欢(并且使用过)Forty-Two提出的解决方案(https://dev59.com/zGzXa4cB1Zd3GeqPY-eH#14199707)。 - yoozer8
好的,谢谢。我很惊讶这个方法真的有效。我以为TempData只能在一个控制器内使用。 - Dmytro
它适用于会话中的下一个请求。添加一个关于它的链接。 - yoozer8

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接