views:

104

answers:

2

I have a scenario where I need the following functionality:

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");
}

I need JsonResult in the View Page, but the problems are as:

  1. As RedirectToAction returns redirecttorouteresult I can't directly return the JSonResut
  2. As I need the Session in ActionC I can't instantiate Controller and call the action.
A: 

This may not be the best approach...

Its hard to tell, but drying up the controllers, and getting moving out the business logic may help. It looks like you want to maintain the functionality of Actions B, and 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");
}

BTW, you should check out Ninject, Castle Windsor, Structure Map, or any other DI/IOC container, to help you test this logic (and make it dryer). Try searching for ninject asp.net mvc 2 tutorial

Porter
A: 

Can you not refactor you controller actions to extract the Some manipulation and calculations into another class or service layer function call.

As I need the Session in ActionC I can't instantiate Controller and call the action.

There is nothing stopping you from using the Session in ControllerA.ActionA . The following is not exact, but may help you ..

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");
    }   
}

Edit: Have a look at the source code from here http://www.lostechies.com/blogs/jimmy_bogard/archive/2010/07/23/mvcconf-slides-and-code-posted.aspx. I think that Jimmy Boggard's, approach may be useful and provide you with a way to call 'other controller' actions. You comment ' I can't change the behavior of the action. And to refactor it will take time which I do not have.' to me indicates the journey on the road to unmaintainable code. Refactor, Refactor, Refactor - the benefits of doing it now will save you hours of heart ache at a later stage. And based on the question, I think it has already started.

Ahmad
I have listed only some of the actions. But there are about 20 actions in each controller. Most of these actions are interrelated. As the this application is already live, I can't change the behavior of the action. And to refactor it will take time which I do not have. So I can't create a different class like Utilities and write the methods that can be used by the actiion. i have to call the action.So is there anyway I can achieve my goal?
SP249
@SP249-"Interrelated actions", "can't change", "already live" - to be blunt, your app sounds like a poster boy of anti-SOLID. The other aspect is that you mention is that you cant change the behaviour of the actions, yet you are asking for a solution that will require a change to the live system and your codebase. The solution provided does not change the behaviour of an action(s) but rather provides you with a way to make your app a bit more maintainable by encapsulating the behaviour in a way that can be re-usable within your entire app.The interdependencies bet controllers will decrease.
Ahmad