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
Related
When I have RenderBody or RenderSection, and I try to use a template directly, it gives an error:
The file "~/Views/Home/Form.cshtml" cannot be requested directly because it calls the "RenderSection" method.
I have a form that has some basic fields, but in one instance, I want to extend the form with more fields (the Model inherits from the original).
Maybe I should just create the basic fields in a shared file, but this would work if it wouldn't throw the error above...
In Razor, everything is a view. "Partial views" are just views that don't utilize a layout, while the more traditional "views" are views that do. A "layout" is merely a view that at least calls one method, RenderBody. RenderSection, is likewise layout-specific. By making a view a layout (by calling methods like RenderBody, RenderSection, etc., it can no longer be used as "view" or "partial". This has to do with the way Razor handles view processing. By the time something like a partial is being rendered, there's nothing that can be done with something like RenderBody, so Razor raises an exception.
Long and short, you can't use a layout as a partial, which seems to be what you're trying to do here. Without more information about what it is that you're actually trying to achieve, it's not really possible to help you further than that.
We have an MVC 3 Razor web project where we specify a custom base class for our views. In the InitializePage method of this base view class, we are doing some initialization and saving an object to the ViewBag. This information serves as sort of a "model" for our layout pages. One piece of information here a structured context menu that is rendered in the layout pages. The items on this menu can change, depending on the user that is logged into our site.
My question is how I can unit test this code that runs in the base view class. Since this code only runs when the view is rendered, do I have any choices other than mocking up a controller context under which to execute the view? I've seen some samples on the internet about doing that and it seems like it's more trouble than it's worth.
Any thoughts would be helpful. Thanks!
To me, the obvious solution would be to extract that code (or at least the bulk of it) into a method of another class. Then your View class should simply pass the appropriate values to that method, making its InitializePage method sufficiently simple that it has no need for unit testing. You can unit test the method independently of the View class.
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.
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"%>