tags:

views:

223

answers:

3

On the main page of my site, I would like to show several views which rely on their own controllers for data retrieval. I do not want to retrieve anything from the DAL in my Home controller.

For example, I want to show view listing top 5 news, a view with random quote from the database, another view with the users shopping cart contents, etc.

After Googling around, I found RenderAction method which is almost perfect, but it's not available in RC1, only in Futures, and apparently, it has some issues.

I found RenderPartial as well, but that relies on the main controller to pass data to the view.

Additional clarification:

The main reason I do not want data access logic in the Home controller is to avoid repeating the code and logic. I will use top 5 news view in several pages/controllers. I do not want to repeat data retrieval in every one of them. I already did separate a lot of logic and validation to business layer. The solution I'm after is RenderAction or UserControls as in classic ASP. I know i can use them in MVC as well, but... whats the point? I mean, if what i'm asking is too complicated or too absurd (reusable UI components), then MVC is definitely not for me, and I'd consider it seriously inferior to classic ASP.NET, because this requirement is really simple.

+1  A: 

What you're asking is to basically not perform data access in the HomeController, this seems like a dogmatic approach. I would consider either using RenderAction from the Futures assembly (not sure what's wrong with it, I use it in a number of projects) or SubControllers from MvcContrib.

Chad Moran
Dogmatic? I'm simply trying not to repeat a lot of code around...
mitch
Well then there's a design solution to this behind the view. Try creating another layer between controller and DAL, maybe a BLL.
Chad Moran
+1  A: 

While I can understand the desire not to replicate functionality in multiple controllers, I don't understand the reluctance to have your Home controller interact with the DAL. I think the partial view is definitely the way to go. My solution to not replicating the functionality would be to push the code that generates the data for the various views into your business or data layer. You could then reference it from each of the required controller actions that use the partial views. Putting it in the business layer could isolate the controller from your data layer, if that's what you desire, but I still think it's the proper job of the controller action to obtain and provide the data to the view.

Another potential solution would be to populate the view generated by your Home controller via Ajax callbacks to the various controller actions that generate the required view components. The drawback to this is that it doesn't fail gracefully in the absence of javascript in the browser.

EDIT

Based on your clarification, I would suggest implementing a base controller that fills the ViewData for the shared controls in ActionExecuted (so that it's done only when the action succeeds). Derive your other controllers from the base controller when you want to inherit this behavior.

tvanfosson
Sure, I'll fill the ViewData collection with the list of latest news, with the user profile, with the shopping cart... and repeat that in every page, effectively duplicating the code (no matter how small).
mitch
A: 

If you really don't want to use RenderAction, then the only other option you have is to load the necessary data pieces with action filters. Your home controller could then look like this:

public class HomeController : Controller
{
    [RequireNews]
    [RequireQuotes]
    [RequireCart]
    public ActionResult Index()
    {
        return View();
    }
}

These action filters could be re-used where they are needed. You might also choose to place these on the controller class itself.

Ben Scheirman
I absolutely want to use RenderAction, but if the team throws it out of RC... then I'm wondering why? I don't want to base production code on some Futures concept which might also go away...
mitch
I wouldn't worry about using it. I use it in my applications. If it does go away in the future, you can look to MvcContrib to provide a replacement, as I know many folks are using RenderAction.I'm also not sure why the team has it in futures, but I can ask...
Ben Scheirman
RenderAction is inherently dangerous as you don't know what kind of result the action will return, perhaps something other than a partial view. Using filters or putting common data generation code in a base controller is a better way to make sure that the view data is available for partials.
tvanfosson