tags:

views:

693

answers:

6

Just read a post about MVC best practices. Couple parts of the post described building helper methods to link to actions on the controllers. Here's a clip:

1) Create Extension methods of UrlHelper to generate your url from Route

Avoid passing the controller, action or route name as string, create extension methods of UrlHelper which encapsulates it, for example:

public static class UrlHelperExtension
{
    public static string Home(this UrlHelper helper)
    {
        return helper.Content("~/");
    }

    public static string SignUp(this UrlHelper helper)
    {
        return helper.RouteUrl("Signup");
    } 
}

I can see how this would shorten links used in views... but I don't see how this is a "best practice". Perhaps I'm simply overlooking something. Should I be doing this to build my links? Are there benefits to this I'm just not seeing?

He even goes on to say that stylesheets, images, and javascript helpers should be made...

+2  A: 

If you make a mistake when writing a URL as a string, it won't be caught until runtime. This way, attempting to refer to a route that hasn't been created as an extension method will create errors at compile-time, which you can quickly correct (even earlier, if you use Visual Studio). If you discover a mistake in the way you formulated a route, you only have to fix it in one place.

Although, instead of cluttering your UrlHelpers with extension methods, it might be better to have a static class called something like CommonUrls that holds static readonly properties (or static methods, if you prefer).

EDIT: I just realized that you would need to pass an instance of your UrlHelper to the CommonUrls class. Silly me. In that case, extension methods probably are the right tool for the job.

David Brown
I wonder what kind of performance overhead this induces? I'm sure it would be minuscule, but overhead is overhead.
Chad
Very little, I would say. Although if you're interested, it might be a good idea to make a little test project and run it through a profiler to see exactly how much of a performance penalty is involved.
David Brown
+3  A: 

I probably wouldn't do this unless the route is referenced in multiple places. I can see the value in doing this, and I have implemented HtmlHelper extensions for adding style sheets and javascript includes to add the ability to use "versioned" links, but my common links are included as ActionLinks in a UserControl (menu) and for most other things I use either ActionLink or BeginForm/AjaxForm to reference the action. In some respects it feels like creating new methods for all but the most commonly reused links is adding complexity for very little value -- the kind of value that you would get from some simple manual testing of your UI, which you'd have to do anyway.

tvanfosson
+2  A: 

That's one person's opinion of what a best practice is. There are a few cases where it might be nice. If you have people working with the views while the URL structure is still being worked out you won't have to update the views once the URLs are finalized.

John Sheehan
That's true... didn't really think about that since I'm a one man show. ;D
Chad
+1  A: 

I don't see this as a best practice. For one thing you're going down the path of burying structural specifics down in a bunch of extension methods. (Although you could use resources for the paths, it would mean high-friction changes.)

Further, at what point do you stop? For a site of any complexity you're going to need a lot of these helpers.

I've used a somewhat similar approach when referencing stylesheets, javascript, favicons, etc. although I use HtmlHelper rather the UrlHelper extensions as conceptually I think they're more suited to the task.

Further, because such things are typically added to a master page only, there's no issue with simply passing the complete path into the helper and having it construct an entire tag - rather than just resolve a URI.

Derek Lawless
+2  A: 

Should anyone else happen to stumble on this old post, I would suggest using the T4MVC templates by David Ebbo: See his latest blog post here.

Oskar Austegard
+1  A: 

I'm using this approch. It's very useful when your application sitemap is subject to changes. And yes, you need a lot of those (I my extension class count 1800 lines, with comments)

Main difference, in my case, I build the URL using a strongly-typed builder. It looks like this :

    /// <summary>
    /// To campaign 'transfer credits' page
    /// </summary>
    public static string ToCampaignTransferCredits(this UrlHelper helper, int? idCampaignSource)
    {
        return To<CampaignController>(helper, c => c.Transfer(idCampaignSource));
    }

I think this is a very good practice (IMHO) for some reasons :

  • you have a clear separation between navigation available page/actions and your controllers. I recently had to move methods from one controller to another, and it worked without pain/refactoring/testing.
  • it's compiled so if you change a controller's method signature you are awared of the changes to do (and you only have 1 or 2 changes, no need to check the whole application)
  • you can use inheritance and generics on your controllers like a OOP geek, cascade the calls and whatever you find powerful, this approach will hide all the underlying complexity, leaving simples call in the views.
Mose
Thanks, that's clever. Much appreciated.
Chad