views:

328

answers:

2

I make heavy use of View Components in some of the larger applications I've built in Monorail - What is the equivalent approach in ASP.Net MVC for a view component, that can support sections etc.?

A: 

Phil Haack blogged about creating areas to group controllers into sub-folders/sections similar to MonoRails.

Kris
Sections in a view component in monorail are not the same as areas, they are more like named item templates which can be used by the view component when it's rendering - see ayende's post for a good description:http://ayende.com/Blog/archive/2007/04/08/Building-View-Components-For-MonoRail.aspx
Bittercoder
+2  A: 

Hi

Actually you have several options to create the equivalent of a ViewComponent in ASP.NET MVC, depending in the complexity of your component. I use these two approaches which are the more mvc-ish of the options I am aware of.

1: The simplest thing is to create a ViewUserControl and display it using Html.RenderPartial with the helper. The ViewUserControl is a simple piece of markup with no backing controller (I think you can put a codebehind file if you want). Optionally, you can pass a model object or the entire ViewData dictionary to the view when calling RenderPartial, like this:

<% Html.RenderPartial("TopBar", model); %>

"TopBar" is an ascx page. This works anywhere, in master pages and in normal views.

2: If you want your component to have more complicated logic or to access datasources, IoC, etc, then you can use Html.RenderAction which is an extension method found in the Microsoft.Web.Mvc assembly. I am using this out of the mvccontrib distribution. It works like this, you need to create a normal controller with all the logic you need, then create some views and all of these things become your component, for example:

public class AboutComponentController : Controller {
public IRepository Repository{ get; set; }

public ActionResult Detail() {
 var lastEvent = Repository.FindAll<Auditoria>().FirstOrDefault();
 return View(lastEvent);
}

}

Notice how I have a reference to an IRepository which is going to be injected with IoC (Windsor in my case) and I can do anything a normal controller would do.

Now, in any page (master or normal) where you want to use your component, import Microsoft.Web.Mvc and call Html.RenderAction with the appropriate parameters. This will create a mini mvc pipeline that creates the controller, resolves the view, etc., just like a Monorail ViewComponent. I prefer to use the lambda based variation of the method, like this:

<% Html.RenderAction<AboutComponentController>(x => x.Detail("a message"));%>

Unfortunately, the only way to pass parameters is to use the method call itself, which in turn must be unique in the controller. Still needs some work to resemble a ViewComponent.

I don't use masterpages or layouts in the views of my components since they are composition elements themselves.

Remember that when using the Webforms view engine, you can have strongly typed views if you like to have intellisense when using the Model variable in code blocks.

The beauty of this is that you can mix view engines with these approaches, I usually create the components in nvelocity and display them in aspx pages, etc.

I now there can be issues with caching of the partial views but I haven't run into any so far. I am sure there are other options (like subcontrollers in mvccontrib) but this is usually enough for simple cases. Of course you can use normal ASP.net components in your aspx view pages but that would be cheating right? hehe. I hope it helps.

Thanks for the in-depth response, I've been using partials, but haven't tried render action yet - looks interesting.Unfortunately it still doesn't really help me replace the view components I currently have/love in Monorail which make heavy use of sections (http://ayende.com/Blog/archive/2007/04/08/Building-View-Components-For-MonoRail.aspx) - looks like I might need to do some further investigation to see if there is anyway to emulate this behaviour.
Bittercoder
@Bittercoder were you able to find anything about replacing view components with heavy section use?
Tinister