she swears <i>geek</i> is a term of endearment

Setting Properties using Asp.Net MVC

November 12th, 2008 Rusty

This was a nifty way to set properties in previous MVC drops.  I’ll demonstrate one way to migrate this to the new way of MVC.

<%= Html.RenderUserControl( "~/Views/Components/Pdf/ReportHeader.ascx", ViewData.Model.PrimaryCompany, new { PageNumber = 1, TotalPages = 7 }  )%>

First you’ll need to accept ViewData items in your control.  The path of least resistance is to set your existing properties using new view data items.  This is done inside your user control.

public partial class ReportHeader : System.Web.Mvc.ViewUserControl<Models.Ticker.TickerViewData>
    {
        public int PageNumber { get; set; }
        public int TotalPages { get; set; }
        public string TickerUrl { get; set; }
        public ReportHeader()
        {
            this.PageNumber = 1;
            this.TotalPages = 5;
            
        }
 
        protected void Page_Load( object sender, EventArgs e )
        {
            if( ViewData["pageNumber"] != null ) this.PageNumber = (int)ViewData["pageNumber"];
            if( ViewData["totalPages"] != null ) this.TotalPages = (int)ViewData["totalPages"];
            this.TickerUrl = new gah.Web.Mvc.Helpers.NavigationHelper().GetTickerUrl( ViewData.Model.StockTicker );
        }
 
        
    }

Modify your calling view page.  Notice, no <%=

<% 
            ViewDataDictionary pagingDictionary = new ViewDataDictionary();
            pagingDictionary.Add( "pageNumber", 1 );
            pagingDictionary.Add( "totalPages", 7 );
            
            Html.RenderPartial( "~/Views/Components/Pdf/ReportHeader.ascx", pagingDictionary );
            %>

I was a fan of the old style but this works just as well.  Perhaps someone will write the extension that brings back anonymous property mapping…  :)

RenderUserControl migration from Asp.Net Mvc Preview 4 to Beta

November 12th, 2008 Rusty

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

Had to Roll Back Asp.Net MVC

October 23rd, 2008 Rusty

Early on in the MVC Previews, the method RenderUserControl was provided.  It was a perfect fit for the concept of rendering a "control" or a "partial" as it did all the work of executing the lifecycle of that control and then returned the html as string output.  You could then use that html in any way you saw fit.  You may have wanted to store that output in a database or add it to an object structure and then serialize that as JSON.  Whatever!  You were left to your own ingenuity and resourcefulness to accomplish your business objectives. 

That method is GONE.  There is no equivalent, that I can find, that will give you access to the html output as a string.  It looks like the solution is going to be to replicate that behavior some other way and write all the code yourself.  This is really, really unfortunate.  See, there are a lot of cases where a control from web forms worked in Mvc except for some strangeness.  There might be some view state or a bunch of extra markup that you don’t want or you may have wanted to modify or clean up the html before adding it to your page.  Furthermore, there may be an expected render error that you aren’t able to prevent because the control is compiled and you don’t have the source code.  Wrapping RenderUserControl in a try catch gave you the ability to catch that problem and deal with it.  Gone.  Just gone. 

Since we used RenderUserControl 61 times in our website, I was not prepared and do not have time to refactor and test all that code.  My unit tests will no longer work because I cannot test the output of rendering a control, I can only embed that control in the mark up.  The problems that I was handling before are now going to blow up my page.  I suppose I can inherit from and extend the Controls in question but that is just big waste of time when all I want to do is handle the errors that the author didn’t.

So I’m rolling back to Preview 4 until I have about a week to dedicate to the update.

I suppose I should have known better than to use Preview Code on a production app but my alternative was either Castle or WebForms.  Neither is as pleasing as Asp.Net MVC. 

Asp.Net beta is out and I’m screwed

October 22nd, 2008 Rusty

With each preview release of Asp.Net MVC, I’ve had quite a few issues to resolve.  Most of these were well documented and I was able to resolve them by reading the release notes and the upgrade instructions.  Unfortunately, Beta is a little different.  

Blame it on Apple

I’ve been iPhone bound for a while.  I skipped Preview 5.  I would have caught this issue then and probably avoided the problem that I am currently facing as I believe we wrote most of this code after the Preview 5 drop.  Thanks alot, Apple, for making iPhone development so freakin’ cumbersome!

Rendering Partial Views

One of the features of Asp.Net MVC that I absolutely LOVED was the ability to render a user control to a string and then mess with that html.  Seriously, that capability was incredibly valuable.  Brad Wilson decided to axe it.  He had a Microsoft-typical attitude that he should change the code to restrict the consumer into following his pattern for use rather than leaving it open as it was before.  Yes, Brad, I am angry with you right now…

Listed incorrectly as an added feature…

  • Added support for rendering partial views. You have several options for passing view data to the partial view. The partial view can be rendered by a different view engine than the containing view. Usage is <% Html.RenderPartial(…); %>. This method does not return a string, but instead renders to the TextWriter instance of the underlying response.

Here’s what I had before (yes, I could render partials before):

HtmlContent.AppendLine(
    Html.RenderUserControl( 
        "~/Views/Components/Charts/RatingReturnChart.ascx", 
        this.ViewData.Model, 
        new { Weighted = true, CurrentTimePeriod = requestedTimePeriod }
    )
);

After the html was rendered, it was passed to another control that accepted a string for "other stuff" that it wasn’t responsible for.  There are other ways to solve this problem but this was something that was easy and didn’t violate our desire to keep separate concerns, separate.

Now the damn thing uses the TextWriter attached to the response object.  So much for extensibility and object oriented programming.  Let’s hardwire into the response object, just like webforms.  Nice work, Brad.  Love it.  Great.  Now I have to create a user control and move my page logic into the control because I can’t define my own context and behavior.  Just like webforms.  Hey, are you going to insert view state and post-back on your next big brain storm?  That’ll be swell. 

Back to the drawing board

Where did I put that Rails Recipes book?

Asp.Net MVC - yeaaaaaaaaaaaaaaaaaaaaaah

September 11th, 2008 Rusty

Aw, shucks guys, you rock!  The Asp.Net team: Scott "Gu" Guthrie, Scott Hanselman, Phil Haack, Rob Connery

Preview 5 was released last Thursday.  I’ve been buried in iPhone development so hadn’t seen that till this morning.  Reading the release notes was like receiving a "thinking of you" card out of the blue when you’d been away from home for a very long time.  If I sound dramatic, go build yourself and Objective C project and then fire up Visual Studio and write some Asp.Net MVC.  Its like  jogging with 20 lbs ankle weights for 3 weeks and then coming back to naked ankles.  …but I digress.

Preview 5 brings many of the kick-ass features I missed form Monorail and was hoping the Asp.Net MVC team might build for us. 

Model Class Binding

My favorite feature is "model binders".  This allows you to declare your action parameter as a strongly typed class instance and then marshall the request values into an object before you even hit the action.  Monorail had this built in as a convention where you could pass [param name].[property] from a request key and it would be initialized.  For example: given a class called "Car" with a property "TopSpeed", you could declare your action signature to be: public void Add( Car car) and then, in your html, pass <input type="text" name="car.TopSpeed" /> and magic would instantiate your Car class, set the TopSpeed property and pass it in your car parameter. 

With Asp.Net MVC, you can write ModelBinders to map the request keys to your model class and perform any necessary initialization or validation.  In addition, there a new ModelState collection that you can use for validation issues and awesome integration with the view side of things.  At first glance. it looks like there’s a whole lot of extra work to be done to accomplish this.  However, the team is planning to include standard modelbinder that uses the modelname.propertyname syntax for mapping incoming parameters.  All this ModelBinder goodness is for extensibility in those cases where you want to be super special or where your class is not that uses the modelname.propertyname.

The validation is pretty slick.  Personally, I use jquery.validate on the client side.   The rules that Scott demonstrates reminds me of this jquery library and I have a feeling it wouldn’t be too difficult to write a validation helper that could emit the server-side rules as a jquery registration.  While the jquery plugin does an awesome job on the browser side, it can be bypassed easily and having a server-side backup would be excellent.

Setting the Active Record straight

June 19th, 2008 Rusty

I was asked yesterday whether my new site, beta.ockhamresearch.com, was developed using Ruby on Rails.  In a very indirect way, sort of.  Ok, no, not at all!  Its Asp.Net MVC

Mvc stands for Model View Controller, a popular design pattern for modern website architecture.  I feel it is significantly more productive and effective than the page-centric architecture you find as the default in most web programming languages.  Ruby’s first popular website platform was Ruby on Rails.  There were other MVC implementations out there already for platforms such as Java and Smalltalk.  However, Rails maid it intuitive, productive and even fun.  This led other programmers to favor the pattern for developing websites (such as myself) and led to the development of Castle Monorail in dot net and other variants as well as on other platforms.  Many of these were ports of Rails for folks who weren’t able to use Ruby as their target language for one reason or another.  I had been using Monorail for some time when Microsoft announced the development of Asp.Net MVC.  Microsoft isn’t well-known for open development initiatives and often does things the Microsoft way rather than the conventional way.  The Microsoft Asp.Net team deserves much credit for the current quality of Asp.Net MVC and the integration of tremendous community feedback. 

Why not just use Rails?

Competency

I have very little experience with Ruby.  When I need to write some Ruby code, I need to look up each construct and find examples to work from.  I can code C# in the woods on the trunk of a tree.  Of course, compiling it would be a challenge.

Confidence

I know where Asp.Net and SQL Server limitations are and that the platform can achieve high performance.  I know that Ruby has known performance issues and no roadmap for reconciling these issues.  I’d rather not be the person responsible for overcoming performance issues on a production web server farm when we have paying clients expecting service.  If I can run a commercially supported platform with current licenses and support contracts, I have someone to lean on if anything goes wrong.  Furthermore, I can fix almost anything on Windows but my experience with Linux is feeble.  I aim to change that but, for now, I can provide confidence to my constituents that my web app will not fail due to memory leaks or unusual bugs that are not a result of my code.  Yes, there will definitely be errors in our future but using NUnit, Cruisecontrol.Net, WatiN, Visual Studio.Net and SQL Server will minimize the risk to a more than acceptable level.  I don’t know where to turn for the same thing in Rails.

Community

This is the most important factor.  The above two points are true for all the programmers I’ve worked with over more than the last decadeWe’re all very familiar and invested in Microsoft technologies.  There is no reason to switch if the features are available and productivity is commensurate with alternatives.  If I need help modifying some code because I have too much to do myself or we have an awesome contract pending, I don’t want to be searching in a small pond for good people. For every good programmer, there are a hundred terrible ones that will make a mess of my beautiful code :)  I can’t have that. 

Why Use Rails at All?

I can’t find current data that indicates the trend for what programmers are using but I can tell you my gut feelings and personal observations.  No community growth, in my technology career, has struck me with as much fervor and excitement as the Ruby and Rails explosion has.  These people aren’t Windows haters like Java programmers were.  They aren’t choosing Ruby because that’s where the jobs are (yet).  They are choosing Ruby because they get hooked!  They love working with it.  More often than not, a Ruby programmer dresses hip, is very laid back, uses a Mac, drives a Hybrid.  These are all traits of people with both time and money.  I want more time and money and would like to be hip.  However, I still prefer to burn more gas in exchange for fast times to sixty.  Glutinous, I know.

When do you switch?

Rails still needs to be proven in the enterprise.  My prediction is that this will happen in 2008.  Sites using Ruby on Rails will publish numbers and costs of operation that make it a very attractive alternative to the company standard.  The best place to try Ruby is on a new, small scoped project with just a few very close end users in a highly agile environment.  Don’t be silly and just announce that you are now Ruby and expect all your devs to just pick it up.  On the other hand, it would be a good idea to get some very intense training for your old school programmers (if you have them) because they are accustomed to working within the constraints of their strongly typed, compiled, high performance environment and will not naturally make the appropriate transitions necessary to achieve success, maintainability and scalability in a Rails environment.  Ask yourself if your compiled apps (yes, Asp.Net is compiled) are as fast as they should be and then ask yourself whether your app will still be acceptable at 50% of that speed.  On the other hand, if you have 80% of your hardware capacity remaining, you can probably virtualize and take advantage of your current infrastructure with very little cost.

Try it on like deodorant.  Give it a few days and try a few different activities and then ask your wife if your pits stink.  If not, take it a little further.