views:

334

answers:

3

What I am trying to achieve:

  1. After each view has finished executing I would like to make a separate http call to an external partner.

  2. I need to pass one of the view's content as body of that http call.

What I have so far:

I have a base controller from which all of my controllers inherit from.

I have found that i can override the onActionExecuted() method of the base controller and write my partner http call code there so that it will be executed after each action.

I have written a custom result after reading the article at http://stackoverflow.com/questions/520863/send-asp-net-mvc-action-result-inside-email. which enables me to grab the content of the view. (which is part of another controller that also inherits from base controller).

What I can't figure out:

  1. How do I make a call to the controller action (the one that will render the content for the http calls body) to get the content in my base controller onActionExecuted() method?

anil

A: 

The idea of most MVC frameworks it to make things more simple. Everything breaks down into a call to a method with certain inputs and with certain return values. In a way, you can accomplish what you want by doing something like this:

class MyController {
  public ActionResult Action1() {
    // Do stuff 1
  }

  public ActionResult Action2() {
    // Do stuff 2
  }
}

You can then refactor a bit:

class MyController {
  public ActionResult Action1() {
    // Pull stuff out of ViewData

    DoStuff1(param1, param2, ...);
  }

  public ActionResult Action2() {
    DoStuff2(param1, param2, ...);
  }

  public void DoStuff1(/* parameters */) {
    // Do stuff 1
  }

  public void DoStuff2(/* parameters */) {
    // Do stuff 2
  }
}

Now you can just call DoStuff1() and DoStuff2() directly because they're just methods. You can make them static if possible. Don't forget that you'll likely need to do something about error checking and return types.

Tommy Hui
Hey Tommy,This approach will have me duplicate the method to each controller and then duplicate the method calls at the end of each of its actions.I was looking for a solution (if it is possible) that would allow me to do that from my base controller as all of my controllers inherit from itAnil
A: 
 protected override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        base.OnActionExecuted(filterContext);

            this.ViewData.Model = GLB_MODEL;
            Stream filter = null;
            ViewPage viewPage = new ViewPage();
            viewPage.ViewContext = new ViewContext(filterContext.Controller.ControllerContext, new WebFormView("~/Views/Customer/EmailView.aspx", ""), this.ViewData, this.TempData);
            var response = viewPage.ViewContext.HttpContext.Response;
            response.Clear();
            var oldFilter = response.Filter;

            try
            {
                filter = new MemoryStream();
                response.Filter = filter;

                viewPage.ViewContext.View.Render(viewPage.ViewContext, viewPage.ViewContext.HttpContext.Response.Output);
                response.Flush();

                filter.Position = 0;
                var reader = new StreamReader(filter, response.ContentEncoding);
                string html = reader.ReadToEnd();
            }
            finally
            {
                if (filter != null)
                {
                    filter.Dispose();
                }
                response.Filter = oldFilter;
            }

    }

This is modified version of code from http://stackoverflow.com/questions/483091/render-a-view-as-a-string. I didn't want to render the result of the view to the httpcontext response stream.

+1  A: 

This will call a second controller action from the first controller action within the same controller:

    public ActionResult FirstAction()
    {
        // Do FirstAction stuff here.
        return this.SecondAction(ArgumentsIfAny);
    }

    public ActionResult SecondAction()
    {
        // Do SecondAction stuff here.
        return View();
    }

Doesn't need to be too complicated. :-)

Rap