Razor: Declarative HTML Helpers

Razor: Declarative HTML helpers

The ~/Views/Helpers location as describe in that ScottGu post will not work in MVC 3 RTM. At the time that article was written it was a design idea we were tossing around but ultimately we were not able to implement it.

Putting your helpers in App_Code works but has certain limitations that impact certain MVC scenarios (for example: no access to standard MVC Html. helpers)

Where should I place Declarative HTML helpers in ASP.NET MVC 3

To use the "@helper" feature in Razor you need to place the CSHTML file in the App_Code folder of your app. There is no "Views/Helpers" folder in ASP.NET MVC 3. ScottGu's blog post was written before the feature was fully implemented, and some of the notes there are not entirely accurate anymore.

To call the "@helper" that you wrote you have to include both the filename as well as the name of the helper inside it. For example, if you have this helper:

~/App_Code/MyHelper.cshtml

And this content:

@helper ShowStuff(string stuff) {
<p>@stuff</p>
}

Then you call it like so:

@MyHelper.ShowStuff("some stuff!")

Using MVC HtmlHelper extensions from Razor declarative views

Take a look at Marcind's answer to this question. What you're experiencing is a limitation of putting declarative views in the App_Code folder.

Putting your helpers in App_Code works
but has certain limitations that
impact certain MVC scenarios (for
example: no access to standard MVC
Html. helpers)

How to use built-in HTML helpers within a custom HTML helper?

Unfortunately declarative helpers which are defined in App_Code folder seems to inherit from System.Web.WebPages.HelperPage instead of System.Web.Mvc.WebViewPage from which the normal cshtml files inherit.

It seems that the helper page also has a Html property but it's null.

However, it seems that you can access all this helpers through PageContext.Page. Also you'll need to add some using statements (all the namespaces from the web.config which is located in the views folder) so you can access important extensions methods like Html.BeginForm.

Here is a sample demo code:

@using System.Web.Mvc
@using System.Web.Mvc.Routing
@using System.Web.Mvc.Html
@using System.Web.Mvc.Ajax
@using System.Web.Mvc.Razor
@using System.Web.Optimization

@helper MyCustomHelper()
{
var wvp = PageContext.Page as System.Web.Mvc.WebViewPage;

var Html = wvp.Html;
var Ajax = wvp.Ajax;
var Url = wvp.Url;
var ViewBag = wvp.ViewBag;

// ... Helper code goes here ...

@using (Html.BeginForm("Add", "User", FormMethod.Post))

@Ajax.BeginForm ...

@Url.Action ...

// ...
}

Hope this helps.

How to create a declarative HTML helper in MVC 5

I decided to try use MVC3 way, I added the App_Code folder manually and followed steps from this great article.
And it worked, I needed to restart Visual Studio for my Intellisense to work (which prolonged finding my solution).

I deleted the folder '~/Views/Shared/'

I Added a file MyHelpers.cshtml into the App_Code folder, inside the file I added my helper method:

@helper Tags(System.Web.Mvc.HtmlHelper htmlHelper,
ICollection<MyNamespace.Objects.Tag> tags)
{
foreach (var tag in tags)
{
<div class="tags-div">
@MyNamespace.Extensions.ActionLinkExtensions.TagLink(htmlHelper, tag)
</div>
}
}

And called it in my PostView.cshtml like so:

@MyHelpers.Tags(Html, Model.Tags)

And Viola works as expected... hopefully this helps someone else who ends up in this situation...

When should we use Html Helpers, Razor Helpers or Partial Views?

HTML Helpers are for reusable components. e.g. WebGrid, Pager, etc. These are distributed as assemblies and have no dependency on Razor. Choose this if:

  • Functionality is truly reusable and applicable to any application
  • You don't want people to modify it, or want to version it

Partials Views are a way to split large views into smaller parts to keep things more manageable. They are also useful for reusability that is specific to your application. These are located by the view engine, so you can have the same partial defined in different places (e.g. Views/Shared), allowing you to customize per controller, area or display mode. Choose this if:

  • Functionality is application-specific
  • Want to customize per controller, area or display mode

Local Helpers are a way to execute the same template many times, without having to repeat yourself. You can also use it to break views into parts to avoid deep nesting, but keeping everything in the same file. Choose this if:

  • Functionality is view-specific

Application Helpers (in App_Code) are a mix between local helpers and HTML helpers. Choose this if:

  • Prefer Razor over TagBuilder
  • Don't mind distributing files instead of assemblies
  • Prefer type-safe method-call syntax instead of @Html.Partial(name)


Related Topics



Leave a reply



Submit