【问题标题】:Call action of another controller and return its result to View调用另一个控制器的操作并将其结果返回给 View
【发布时间】:2011-03-21 06:12:43
【问题描述】:

我有一个需要以下功能的场景:

In View I have call as:
$.ajax({
    type: "POST",
    async: false,
    dataType: 'json',
    url: "ControllerA/ActionA",
    data: { var1: some_value },
    success: function (data) {
        if (data == true) {
            form.submit();
        }
        else if (data == false) {
    }
});

// In ControllerA
public JsonResult ActionA(string var1)
{
    /*
 Some manipulation and calculations
 */
 _slist = RedirectToAction("ActionC", "ControllerB", new { var1 = some_value});
 string = _slist.First().ToString();

    return RedirectToAction("ActionB", "ControllerB", new { var1 = var2 });
}

// In ControllerB
public JsonResult ActionB(string var1)
{
    /*
 Some manipulation and calculations
 */

    return Json(false, JsonRequestBehavior.AllowGet);
}

public SelectList ActionC(string var1)
{    
 /*
 Some manipulation and calculations
 */

 Session["STRING"] = some_value;

 return new SelectList(_storeOrderTimeDictionaryList, "Value", "Key");
}

我需要查看页面中的JsonResult,但问题如下:

  1. 由于 RedirectToAction 返回 redirecttorouteresult 我无法直接返回 JSonResut
  2. 由于我需要 ActionC 中的 Session,我无法实例化 Controller 和 调用操作。

【问题讨论】:

  • 您使用的是什么服务器端架构?用它来标记它,你更有可能吸引可以帮助你的人。

标签: jquery asp.net-mvc-2 redirecttoaction jsonresult


【解决方案1】:

这可能不是最好的方法...

这很难说,但是干掉控制器并移出业务逻辑可能会有所帮助。看起来您想要维护操作 B 和 C 的功能。

$.ajax({
    type: "POST",
    async: false,
    dataType: 'json',
    url: "ControllerA/ActionA",
    data: { var1: some_value },
    success: function (data) {
        if (data == true) {
            form.submit();
        }
        else if (data == false) {
    }
});


public Class CalculationsA
{
   public void DoCalculation() {}
}

public Class CalculationsB
{
   public void DoCalculation() {}
}

public Class CalculationsC
{
   public IQueryable<somethign> DoCalculation() {}
}


//_a is declared in Controller A as CalculationsA
//_b is declared in Controller B as CalculationsB 
//_c is declared in Controller C as CalculationsC

// In ControllerA
public JsonResult ActionA(string var1)
{
  _a.DoCalculation(); 
  _slist = _b.DoCalculation().First().ToString();

  Session["STRING"] = some_value;
  _c.DoCalculation();          

  /* your other logic... */

  return Json(retval, JsonRequestBehavior.AllowGet);
}

// In ControllerB
public JsonResult ActionB(string var1)
{
    _b.DoCalculation();

    return Json(false, JsonRequestBehavior.AllowGet);
}

public SelectList ActionC(string var1)
{    
 _c.DoCalculation();

 Session["STRING"] = some_value;

 return new SelectList(_storeOrderTimeDictionaryList, "Value", "Key");
}

顺便说一句,您应该查看Ninject、Castle Windsor、Structure Map 或任何其他 DI/IOC 容器,以帮助您测试此逻辑(并使其干燥)。尝试搜索ninject asp.net mvc 2教程

【讨论】:

    【解决方案2】:

    您能否重构控制器操作以将Some manipulation and calculations 提取到另一个类或服务层函数调用中。

    由于我需要 ActionC 中的 Session,我无法实例化 Controller 并调用操作。

    没有什么可以阻止您使用 ControllerA.ActionA 中的会话。以下内容并不准确,但可能对您有所帮助..

    public class ControllerA{
        public JsonResult ActionA(string var1)
        {
         /*  Some manipulation and calculations    */
             SomeService service = new SomeService();
             _slist = service.ActionThatDoesStuffForActionC(var1);
             Session["STRING"] = var1;
             var firstItem = _slist.First().ToString();
    
             SomeOtherService service2 = new SomeOtherService();
             var service2Result = service2.ActionThatDoesStuffForActionB(firstItem);
    
             // convert service2Result  to a jsonresult here.
    
             return RedirectToAction("ActionB", "ControllerB", new { var1 = firstItem });
         }
    }
    
    public class ControllerB{
         public JsonResult ActionB(string var1)
         {
              /*    Some manipulation and calculations    */
              SomeOtherService service2 = new SomeOtherService();
              var service2Result = service2.ActionThatDoesStuffForActionB(var1);
    
              return Json(false, JsonRequestBehavior.AllowGet);
         }
    
        public SelectList ActionC(string var1)
         {    
         /*     Some manipulation and calculations     */
         SomeService service = new SomeService();
         _slist = service.ActionThatDoesStuffInActionC(var1);
         Session["STRING"] = var1;
         return new SelectList(_slist, "Value", "Key");
        }   
    }
    

    编辑:查看此处http://www.lostechies.com/blogs/jimmy_bogard/archive/2010/07/23/mvcconf-slides-and-code-posted.aspx 的源代码。我认为 Jimmy Boggard 的方法可能很有用,并为您提供了一种调用“其他控制器”操作的方法。你评论'我不能改变动作的行为。并且重构它需要我没有的时间。对我来说,这表明了通往无法维护的代码的旅程。重构、重构、重构——现在做的好处将在以后的阶段为您节省数小时的心痛。基于这个问题,我认为它已经开始了。

    【讨论】:

    • 我只列出了一些操作。但是每个控制器中大约有 20 个动作。这些行动大多是相互关联的。由于此应用程序已经上线,我无法更改操作的行为。并且重构它需要我没有的时间。所以我不能创建一个不同的类,比如 Utilities 并编写动作可以使用的方法。我必须采取行动。那么无论如何我可以实现我的目标吗?
    • @SP249-"Interrelated actions"、"can't change"、"already live" - 坦率地说,你的应用听起来像是反 SOLID 的海报男孩。另一个方面是您提到的是您无法更改操作的行为,但您要求的解决方案将需要更改实时系统和代码库。提供的解决方案不会更改操作的行为,而是为您提供一种方法,通过以可在整个应用程序中重用的方式封装行为,使您的应用程序更易于维护。相互依赖关系打赌控制器将减少。
    猜你喜欢
    • 2023-03-04
    • 1970-01-01
    • 1970-01-01
    • 2017-03-02
    • 1970-01-01
    • 2015-04-30
    • 1970-01-01
    • 1970-01-01
    • 2014-03-11
    相关资源
    最近更新 更多