In the name of DRY I found myself puzzling how one could take a
PartialViewResult and render it as a
string. Simple, right?
In fact, in my head this was already a solved problem. I mean I've written about this before already! Except I haven't. Not really - what I did back then was link to what someone else had written and say "yay! well done chap - like he said!". It turns out that was a bad move. That blog appears to be gone and so I'm back to where I was. Ug. Lesson learned.
So, for the second time of asking, here is how to take a
PartialViewResult and turn it into a
string. It's an invaluable technique to deal with certain scenarios.
In my own case I have a toolbar in my application that is first pushed into the UI in my
_Layout.cshtml by means of a trusty
@Html.Action("Toolbar"). I wanted to be able to re-use the
PartialViewResult returned by
Toolbar on my controller inside a
JSON payload. And despite the title of this post,
PartialView.ToString()doesn't quite cut the mustard. Obvious really, if it did then why would I be writing this and you be reading this?
The solution is actually fairly simple. And, purely for swank, I'm going to offer it you 3 ways. Whatever's your poison.
Yes there was a time when everything was inheritance based. You were rewarded handsomely for making sure that was the case. However, times have changed and (with good reason) people tend to favour composition over inheritance. So, perhaps just for the memories, let first offer you the inheritance based approach:
The idea being that the above method is placed onto a base controller which your controllers subclass. Thus using this method inside one of the controllers is as simple as:
So the next choice is implementing this as an extension method. Here's my static class which adds
I don't know about you but I do love an extension method - it often makes for much more readable code. In this case we can use:
Which I think we can all agree is really rather lovely. Perhaps it would be more lovely if I didn't have to pass
ControllerContext - but hey! Still quite nice.
Although ASP.Net MVC was designed to be testable there are times when you think "really? Can it be that hard?". In fact for a well thought through discussion on the topic I advise you read this. (I'm aware of the irony implicit in linking to another blog post in a blog post that I only wrote because I first linked to another blog which vanished.... Infinite recursion anybody?)
The conclusion of the linked blog post is twofold
- Don't mock HTTPContext
- Use the facade pattern instead
Having testable code is not a optional bauble in my view - it's a necessity. So with my final approach that's exactly what I'll do.
So here I have a simple interface with a
ConvertPartialViewToString method on it. This interface can be passed into a controller and then used like this:
Ah... that's the sweet mellifluous sound of easily testable code.