3

I have two controllers:

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
          }
      }
}

I think I can do something like:

public ActionResult BControllerAction()
{
     try{Something();}
     catch(SomethingException)
     {
         var controller = new AController();
         controller.ModelState.AddModelError("error-key", "error-value");
         controller.AControllerAction();
     }
}

But I suggest it will be architecture breaking approach, and I don't want to do like that. Is there some simpler and safer way, except passing model object?

tereško
  • 58,060
  • 25
  • 98
  • 150
Dmytro
  • 16,668
  • 27
  • 80
  • 130
  • Are you using ModelState to log exceptions? – Forty-Two Jan 07 '13 at 16:01
  • @Forty-Two, exception will be logged in `catch(SomethingException)` block by logger (I simplified this details to focus on main problem I'm interested in), I just need to inform user about this error by another controller's action. – Dmytro Jan 07 '13 at 16:06
  • Your approach is correct. You can execute another controller and return its ActionResult. See [here](http://stackoverflow.com/questions/409049/net-mvc-call-a-controller-action-from-another-controller-action) – semao Jan 07 '13 at 15:59
  • See also, for example, [.NET MVC - Call a controller Action from another controller action](http://stackoverflow.com/questions/409049/net-mvc-call-a-controller-action-from-another-controller-action). If you have logic that two controllers need, then that logic either doesn't belong in a controller or it does, but then in a shared base class. – CodeCaster Jan 07 '13 at 15:59

2 Answers2

3

Depending on what details of the exception you need to pass back to Controller A, I would do something along the lines of

public ActionResult BControllerAction()
{
     try{Something();}
     catch(SomethingException ex)
     {
         return RedirectToAction("AControllerAction", "AController", new { errorMessage = ex.Message() })
     }
}

And then change the signature of the called method to

public ActionResult AControllerAction(string errorMessage)
      {
          if (!String.IsNullOrEmpty(errorMessage))
          {
                //do something with the message
          }
          ...
      }
Forty-Two
  • 7,535
  • 2
  • 37
  • 54
2

You can return a redirect to AControllerAction. You can use the TempData dictionary (similar to ViewData) to share data across such a call (data stored this way will persist to the next request in the same session, as explained in this blog post).

Example:

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");
          }
      }
}
yoozer8
  • 7,361
  • 7
  • 58
  • 93
  • TempData is property of `ControllerBase` class, so I can pass data this way only between actions of the same controller but not between several controllers. – Dmytro Jan 07 '13 at 16:25
  • @DmytroTsiniavsky Just double-checked a recent project of mine. There doesn't seem to be any issue using it across controllers. – yoozer8 Jan 07 '13 at 16:41
  • Although I must admit, I do like (and have used) the [solution proposed by Forty-Two](http://stackoverflow.com/a/14199707/866022). – yoozer8 Jan 07 '13 at 16:42
  • Well, thanks. I'm surprised that this method really works. I thought TempData will work only within one controller. – Dmytro Jan 07 '13 at 18:24
  • It works for the next request within a session. Adding a link about it. – yoozer8 Jan 07 '13 at 19:30