MVC helpers

The other day I was creating a view for a MVC 4 site, and I needed a value from the web config. I thought I would need to get the value from the view itself. At least I thought I did.

The short version of what was going on was that an ajax call was being made from the view to create something on another system that would yield information such as successful, the newly created id, and maybe an error message if something went wrong. The base URL to this other system is stored as a transform value in the web config based on the environment the site is deployed to. Different environment means a different URL. My initial thought was to just build the URL based on the output from the response.

If you’re reading this and thinking that course of action is wrong; you are correct. And I’ll get into why it’s wrong, but first I want to walk through my process. Sometimes when you’re too close to the fire you don’t see the other problems around you. At the time I wasn’t really thinking it through.

The first idea that came to me was to create my own helper collection. Something like MyOrgName dot function or MyTeamName dot function. For this example I’ll just call it Adam dot function. The function I was creating was going to get a web config value, so I wanted the helper to be something like @Adam.GetWebConfigValue(“mykey”)

The basics of creating a razor helper are to create (if you don’t have one) an App_Code folder for your project and then a .cshtml file that will contain your code for your helper. Following along with what I said before about calling my helper collection @Adam, the file that needs to be created is Adam.cshtml. Inside that file would be this code:

Warning: Remember that each time you hit the web.config that’s an I/O hit. So even if you were to go this route, you should store this value as a hidden value if you’re going to reuse it throughout the page. Imagine creating a loop with this function inside of it, each loop would cause the system to read the file.

This function works, but is it right? That’s the question that I found myself asking. What other approaches are there? Well you can create an extension for the HtmlHelper built into MVC 4. For this you could create an extensions class and have a method like this:

To use this you would call it as if you were using @Html on your view.

@Html.GetWebConfigValue("mykey")

We now have two approaches at solving the same problem. Both are pretty much doing the same thing but they both have pros and cons. Creating you’re own helper using razor is the most portable. It’s just a razor view that can be edited with out needing to be re-compiled. And because it’s a cshtml file, it can be shared or reused in other projects if that is what you are really wanting. If you were on a team that managed multiple MVC projects or even if you were a part of an organization that had teams managing multiple MVC projects and you wanted a way to share common helpers. This is a great idea as a concept; but again, this isn’t really ideal in the context of this method that gets app setting values from the web.config file. This particular method can be abused in a hurry and the result would be performance degradation.

Extending the HtmlHelper is less portable in the sense that it needs to be compiled. It’s still portable if your projects are properly tiered out in a way that this would sit in a base common library. You could then distribute it if you’d like. The down side to this is that you are still leaving the work on the view. Just like the other solution, this method can be abused and cause performance degradation.

The solution I came to was to do the formatting on the back end before the data even gets back to the controller to serve to the view. It’s simple and should have been right there like looking in the fridge for something that’s right in front of you but you still can’t see it.

If my view has the intention of showing a URL then a URL is what needs to be served to it by the view’s model. Earlier I said that the view was getting a success, id, and error message. Really what it should be is success, url, and error message. And if the controller were being fed the data by a service that I didn’t control, I would say it’d be alright for the controller to do the transform of the ID to URL on the controller. However the service layer that is supplying the controller the data is something I can control and make sure that that is where all the work is being done.

What we are looking at is something like: External Service -> Manager -> Controller -> View

My manager class is really what will handle the formatting of the ID to URL for the external system. By doing this I’m opening up this entire process for reuse, because today this method of creating something new on the external service is being passed back to a MVC view. But that’s not to say that tomorrow I’ll need to expose this process through a web API of some sort. In that case my process is already set up and all I would have to do is open up an endpoint for consumption by other services. Looking something like: External Service -> Manager -> Web API

There will always be multiple ways to solve problems with multiple steps to take to get to that solution. Ultimately taking a step back to reflect on what I’m doing has always helped me get to the right solution for the problem.