Using Sections in Editor/Display Templates

Using sections in Editor/Display templates

You could proceed with a conjunction of two helpers:

public static class HtmlExtensions
{
public static MvcHtmlString Script(this HtmlHelper htmlHelper, Func<object, HelperResult> template)
{
htmlHelper.ViewContext.HttpContext.Items["_script_" + Guid.NewGuid()] = template;
return MvcHtmlString.Empty;
}

public static IHtmlString RenderScripts(this HtmlHelper htmlHelper)
{
foreach (object key in htmlHelper.ViewContext.HttpContext.Items.Keys)
{
if (key.ToString().StartsWith("_script_"))
{
var template = htmlHelper.ViewContext.HttpContext.Items[key] as Func<object, HelperResult>;
if (template != null)
{
htmlHelper.ViewContext.Writer.Write(template(null));
}
}
}
return MvcHtmlString.Empty;
}
}

and then in your _Layout.cshtml:

<body>
...
@Html.RenderScripts()
</body>

and somewhere in some template:

@Html.Script(
@<script src="@Url.Content("~/Scripts/jquery-1.4.4.min.js")" type="text/javascript"></script>
)

RenderSection and EditorForModel in asp.net MVC

Sections work only in views, not in partials. An editor template is a special kind of partial. It's bad practice to put javascript in partials anyway, so I would simply declare the section in the Edit.cshtml view.

But if you very much insist on putting your scripts in the middle of your markup, since Razor doesn't support sections in partials, you could implement custom helpers to achieve that.

ASP.Net MVC 3 Display-templates and Editor-Template Custom Location, how to?

Danny is correct. The Templates are found the same way that Partial Views are found.

By default the WebFormViewEngine and RazorViewEngine are going to search the following locations for a template.

For display templates:

~/Views/{controller}/DisplayTemplates
~/Views/Shared/DisplayTemplates

For editor templates:

~/Views/{controller}/EditorTemplates
~/Views/Shared/EditorTemplates

I think the name of the sub-directories (i.e., "DisplayTemplates" and "EditorTemplates") are hard-coded into MVC somewhere (I know it's open source and I could find it, but I'm not going to).

I think the easiest way to change the location somewhat is to override the ViewEngine. My custom ViewEngine is pretty complicated at this point, but I suspect you could get away with the following.

Let's say you want your templates to be in ~/Views/Templates.

Create a class that inherits from the view engine you're using now (probably WebFormViewEngine or RazorViewEngine). Add an empty constructor. It should looks like this:

namespace MySite
{
public class MySiteViewEngine : RazorViewEngine // <<-- or WebFormViewEngine
{
public MySiteViewEngine()
{
// We'll put some code here in a later step
}
}
}

Now, add the following lines to the Application_Start method of Global.asax.cs:

ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new MySiteViewEngine());

At this point, compile and run your application. Everything should be running exactly like it is running now. You're basically using the same view engine you were using before.

But now, we want to add a location to search when looking for PartialViews. This is simply done by adding to the PartialViewLocationFormats. So, now in the constructor of your custom view engine, you want to add to the base class' array like so:

base.PartialViewLocationFormats = new string[] {
"~/Views/Templates/{0}.cshtml"
}.Union(base.PartialViewLocationFormats).ToArray<string>();

A couple of notes about the above:

  • The entry above will make it so that your view engine looks for the String display template at ~/Views/Templates/DisplayTemplates/String.cshtml.
  • The location format in these view engines includes the file extension, so if you're using Razor/C# use "cshtml", Razor/VB use "vbhtml", WebForms add "aspx" and "ascx".
  • The way I'm doing it above, I'm adding my location format to the top of the list but keeping all the default locations. You might consider removing those.
  • Watch the current formats and you'll see that you will also get a controller in the {1} position in the format, so if you wanted to have a Templates directory underneath every controller you could.
  • Careful, once you get started moving things around with a view engine, it gets addictive. You might find yourself moving everything around.

Good luck.

How can Editor Templates / Display Templates recognize any Attributes assigned to them?

The built-in attributes, such as [Required] assign different properties on the metadata (see the blog post I have linked at the end of my answer to learn more). For example:

public class MyViewModel
{
[Required]
public string Foo { get; set; }
}

would assign:

@{
var isRequired = ViewData.ModelMetadata.IsRequired;
}

in the corresponding editor/display template.

And if you had a custom attribute:

public class MyCustomStuffAttribute : Attribute, IMetadataAware
{
public void OnMetadataCreated(ModelMetadata metadata)
{
metadata.AdditionalValues["customStuff"] = "some very custom stuff";
}
}

and a view model decorated with it:

public class MyViewModel
{
[MyCustomStuff]
public string Foo { get; set; }
}

in the corresponding editor/display template you could fetch this:

@{
var myCustomStuff = ViewData.ModelMetadata.AdditionalValues["customStuff"];
}

Also you should absolutely read Brad Wilson's series of blog posts about what ModelMetadata and templates in ASP.NET MVC is and how to use it.

PartialViews - Not Using Shared Site.css in Editor/Display Templates - ASP.NET MVC 3

_ViewStart is only applied to Views that are rendered, this is determined on how you render the view. E.G using RenderPartial or returning a PartialView from a controller returns only the contents (and nest partials) of the PartialView that you are targetting.

If the _LayoutFile applied to every view and every partial view then you would end up with pages like so:

<html>
<head />

<body>
<html>
<head />
<body>
<!-- Actual Partial View Content -->
</body>
</html>
</body>
</html>

When a page is rendered all of the the _layout, the view to be rendered, any partial views and any nest partials or editor/display templates are built into a single page and returned to the client so any style sheets that are referenced by the _Layout master will be applied to this now flattened heirarchy of (Partial)Views.

Have you inspected the output HTML to make sure that is as expected? It may not be a problem with the views.

Using Editor template for varying display

You could use the [DisplayFormat] attribute on your model:

[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:00.00}", NullDisplayText = "")]
public decimal? Price { get; set; }

and then to display:

@Html.DisplayFor(x => x.Price)

and to edit:

@Html.EditorFor(x => x.Price)

How are people using Editor/Display Templates vs. Html Helpers?

EditorFor and DisplayFor are the most powerful aspects of MVC 2 and in my opinion should be used and abused as much as possible.

Hop over to Brad Wilsons blog and check out how you can extend the Object templates to quickly whip out convention based screens from ViewModels decorated with attributes:
http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-5-master-page-templates.html

I'm using this technique in a current project and so far not one line of HTML has even been written for an individual screen. :D

I've defined a section - now I want to remove it

What's the problem? Use VisualStudion Search:

Ctrl+F -> Entire Solution -> @section title

Even more - you can use RegularExpressions in Search so you can do it like this:

@section title ?{.*(.*\n)+?.*}

Note that .* button pressed. That means that your search expression is Regex.
Now you can just replace your section across entire solution/project with this approach with Empty string.

Sample Image



Related Topics



Leave a reply



Submit