RenderUserControl migration from Asp.Net Mvc Preview 4 to Beta
This is what I used to be able to do:
string html = Html.RenderUserControl( "~/Views/Components/SomeControl.ascx", ViewData["SomeVDKey"], new {Width=200})%>
Nostalgia makes me weep. For a short time, we Asp.Net developers had something so powerful, so flexible, so lovely, so easy to work into any scenario… well, its gone now, get on with it.
After much research, I eventually gave up on my desire to render user controls to a string. The Mvc team is trying to provide a consistent design pattern and felt it was better to require you to execute actions when you want html output. (Its the "we know best" attitude that gets me so fired up). Along the same lines, properties on controls are no longer accessible because some view engines may not respect the object structure and extending the IView or IViewEngine interface would complicate things on that end. Ok, I concede to your values and narcissistic tendencies.
Need begets innovation
Then I came across a place where I absolutely needed my html pre-rendered to a string. My WebForm-based ascx would not accept the child content I was placing in it. The behavior was that any script inside my tags would cause the outside control to fail render yet it rendered the child content - weird and completely unusable. The original design used RenderUserControl to create the html and then set that as a string property in the container control. No, not perfect. But it worked! It is WebForms smashing heads with MVC and the result is a blank page (and a blank stare). I either had to completely reinvent the features or come up with some bridge to bring it back to life.
I really didn’t want to render an action from the view because I had all the data I needed already loaded in ViewData. It hurts my sensibilities to load the whole stack and hit all the expensive resources a second time just for a small part of the page.
Render Html from the Controller
Mike Hadlow had a better idea than all of us. He realized that this need to render the output of an partial page and do something with it falls in the realm of business logic and probably belongs in the controller anyway. He created an extension method for Controller that captures the output of an action as a string of html. Now I can stick that in ViewData and pass it to the view as finished html. Since I call this method after initializing ViewData, it does not require that I make an entire round trip or hit my database or other resources again. Excellent. Thank you so much!
What I have now:
string html = this.CaptureActionHtml<ResearchController>(c => (ViewResult)c.RatingsReturnChart() );
I’m using the extension posted here: http://mikehadlow.blogspot.com/2008/06/mvc-framework-capturing-output-of-view_05.html
That’s not bad. Not bad at all. Now I can pass that html to my view in the ViewData and modify my view to pull it from there rather than render itself. I can deal. Thanks for the save, Mike
November 23rd, 2008 at 5:21 pm
Yeah Mike Rocks. I had the pleasure to meet him at last years DDD.
With luck the MVC functionality will not change post Beta, so you should be free to fully refactor all your web forms. We moved to the entire Rentals.com back-end to MVC in six weeks using just two developers! Performance is stunning and for the first time in the company’s history we have designers modifying our pages themselves - the pages are really starting to pop.
December 12th, 2008 at 3:40 am
You miss the point. RenderUserControl is removed because it is superceded by RenderPartial:
http://eric.polerecky.com/archives/htmlrenderusercontrol-and-aspnet-mvc-preview-5/
December 16th, 2008 at 6:35 pm
Jean-Daniel Dufas, I did not miss the point. I suggest you read before you comment.
RenderPartial does not, at all, support the capabilities that renderUserControl did. I believe you never bothered to read the article or you’d see that I had a need to render to string, something that RenderPartial does not do. In addition, you can no longer set properties on controls via Render helper methods. Everything that will be used by the control MUST be passed in ViewData. This is a disappointment and serious shortcoming when using controls designed for web forms that worked just fine in Preview4. I was able to migrate my code, with significant effort, to work in beta. However, several design choices were no longer possible and I had to employ a few questionable hacks to get the job done quickly. No matter, its in the past. Mvc is what it is and it still rocks!