I am increasingly finding situations where my ASP.NET MVC view requires some logic to perform layout. These routines have no place being in either my model or my controller. I have 3 options:
Write lots of <% %> inline in the view.
Write less <% %> in a number of partial views.
Write an HtmlHelper Extension method.
It is the last option that confuses me. Is it OK to do this if the logic is specific to only that one view? The extension would be 'visible' to the Html object of every other view, and it will never be needed.
Any suggestions?
I personally prefer option 3 ("Write an HtmlHelper Extension method") because those bodies of code lend themselves to be easily unit testable.
I really do wish extension methods could be placed on internal or nested classes because you are right, you will begin to pollute your namespaces with tons of extension methods which are only used in one View.
I'd recommend sequestering these HtmlHelper extension methods in static classes in a custom namespace per View that you manually reference in the View so as to limit the number of extension methods available throughout your project.
I would, generally, limit both partial views and extension methods to reusable components, but am not pedantic about it. If you feel that either one improves the readability of your code, then go ahead and use them. You might want to consider a separate namespace/helper class for helper methods that are only used by one set of views -- sort of like segregating your partials per controller.
You might also want to consider using more whitespace (even though it's the silent killer) to improve readability. I've implemented output compression in my base controller to limit the impact of whitespace on download time.
Is it OK to do this if the logic
is specific to only that one view?
Yes. Read on...
The
extension would be 'visible' to the
Html object of every other view, and
it will never be needed.
No true. It depende how you register the extension method for the view. This is only the case if you add the namespace to the web.config namespaces section.
If you want to use the extension method on a single view just import its namespace to the single view:
<%# Import Namespace="NamespaceOf.Your.ExtensionMethods.ForThisViewOnly"%>
Related
Is it possible to override the class file location of a framework class via classmap and autoloader? If yes, then how?
Example: I want to override Zend\Form\Fieldset, so that everywhere in the framework where Zend\Form\Fieldset is referenced, I want it to use my own class file instead of the original.
Motivation: When updating the framework, I want to keep my modifications safe from getting overwritten.
Known alternative: Modify the code in the framework.
Disadvantage: Modification gets lost when updating the framework.
writing the same class (FQCN) at another location is generally a bad idea. This causes two classes which are equally named to live in two separate locations. It's a much better idea to create your own Fielset in your own namespace. Say, Application\Form\Fieldset.
You can extend the ZF2 fieldset by your own. Then reference this new fieldset class and its all much more maintainable.
The downside of this method is you don't automatically use the new fieldset class. You have to reference the Application\Form namespace in every form you use. On the other hand, this makes it much more clear to other users of you code what exactly happens: there are no unexpected consequences using ZF2 code.
The only remark I have to make here is, for what do you need another fieldset? If you think you need that for view helpers, that's not true. You can modify the view helper to render fieldsets without modifying the Fieldset form class itself.
This is actually a follow up question to this. When is it better to use a partial view and when is it better to use a view helper?
View helpers
Are normally used if you need to add some repetitive/complex logic within the view. A good example of this are some of the already provided view helpers, such as the Zend\View\Helper\Url.
The Zend\View\Helper\Url is designed to abstract away the repetitive construction of URLs, which otherwise would be considerably messy (and error prone) to do each time you need a link.
echo $this->url('zfcadmin/admin', array('action' => 'index');
/** /admin/home **/
The great thing regarding all view helpers is the ability to provided varied data, to a simple API, and have the output be constructed and returned to the view without the view being aware of how the data was generated.
In the case of the URL view helper; There is complex interaction with the Router and it make sense for all of this to be completed in one place.
View Partials
Conversely, view partials are all about "injecting" HTML (or other view data) fragments into other templates. They reduce the need to repetitively write the same HTML structure where only some of the variables are different; Allowing you to create views scripts as reusable 'templates'.
The documentation states
The Partial view helper is used to render a specified template within its own variable scope. The primary use is for reusable template fragments with which you do not need to worry about variable name clashes
I would often use a view partial where there is a small block of HTML that should be reused either as as "widget" or something within a loop.
Note
As there is a clear distinction between what the view partials and view helpers are trying to accomplish, you will often use them in tandem to create your final output. For instance a view partial that you include with $this->partial('/module/foo/bar.phtml', array()); may actually use a view helper within the '/module/foo/bar.phtml (as it is also a view).
Note 2
Just to confuse you even more, when you use $this->partial(); in your view; You are actually using the built in partial view helper Zend/View/Helper/Partial
I am simply looking for how these two are different and what are their pros and cons?
It seems you can do all with partial views that you can do with templates.
If you are referring to EditorTemplates (rather than inline timeplates), then there are some big differences. First, partial views require you to specify your view when you use them, while templates work on the type of the data object.
Second, because templates work on data types, then when you make a change to the template, it changes it everywhere that type is used, not just where the partial view is used (this can be a disadvantage as well in some cases).
Third, templates are passed additional information that partial views are not, in particular you recieve Model Metadata, such as that created by attributes.
if you mean "inline helpers", they are simply an easier way of building the equivalent of HtmlHelper extension methods - but they are only for use in the specific view. partial views, on the other hand, can have more logic behind them (via their controller) without violating MVC and they can be easily reused from multiple views
I am trying to refactor my views a bit and up til now i have been using the built HTML helpers but i thought i would create my own - they're extension methods right?
I wonder if anyone can confirm or give advise when an HTML is needed? I think i once saw a document that said if you use 1 IF statement in your views encapsulate it into a html helper - would anyone agree with that?
With regards to creating html helpers, would it be better to create my own class rather than add extension methods to the HTML class that ships with MVC? Any body have ideas on this?
Or possible i shouldn't bother with HTML helpers and just use the built in ones and continue to use my IF statements within views.
Thanks in advance
Use HTML helpers when you want to encapsulate the output of a piece of HTML markup that can take varying values.
I'd recommend creating them as extension methods to HtmlHelper rather than creating your own class, as your own class won't be available inside of the default ViewPage without either instantiating a new instance inside of the View or subclassing ViewPage and using this in the View (or passing in on the model, but that's just wrong!).
HTML Helpers are extension methods. I can confirm as well that I too use the 'if' rule when it comes to views. Any view logic coded should, IMO, be in a helper.
You can use helper to render custom markup, or control which markup(ie existing view) is displayed.
Not too sure about the ease of this, but it does lend itself to more unit testing (please comment on this aspect if someone has more info).
With regards to creating html helpers, would it be better to create my own class rather than add extension methods to the HTML class that ships with MVC? Any body have ideas on this?
If I understand correctly, in this respect my suggestion would to separate your helpers into their own classes. The reasoning behind this for me would be that you easily know when looking at your views what are standard helpers vs the ones you've created. I think this will improve maintainability.
i shouldn't bother with HTML helpers and just use the built in ones and continue to use my IF statements within views.
I'd say No! (or it depends). One of the benefits of using a helper would be to reuse the same view logic in multiple views as opposed to re-coding the same if statements. This means your code is more DRY, which is always better. In the event you need to debug some weirdness error, you only need to look in one place, the newly created helper.
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...
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.
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.
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.
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.
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.
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.