MVC3 Display templates - asp.net-mvc-3

I've created custom Editor templates and Display templates. I've placed each of these types in a folder within my views folder. The folders were named either EditorTemplate or DisplayTemplate, depending upon which type of template was created.
So, now I can use EditorFor to use my custom editor template, or DisplayFor for my custom editor template.
I would like to create a custom template for a LabelFor, but I haven't found an example of this. Would I create a folder named Labeltemplate in my Views folder and add it here?
UPDATE
The reason I was trying to extend the LabelFor was to handle a Property that is of type KeyValuePair. I want to use the Key of this property as the Label, and the value as the Display. I asked a question here about the DisplayFor to handle the Value.
My solution ended up as>
#Html.DisplayFor(m => m.MyProperty, #Model.MyProperty.Key)
Thanks,

LabelFor doesn't use any templates. It is hardcoded in the MVC source code and it spits a <label> no matter what you do.
You will have to write a custom html helper if you want to modify this behavior.
On the other hand if you want to use templates you have to use EditorFor/DisplayFor helpers. So, since a label is for displaying purposes you could use a display template and instead of using Html.LabelFor(x => x.Foo) use Html.DisplayFor(x => x.Foo). As far as the custom template is concerned, either you decorate the Foo property with the [UIHint] attribute or pass it as second argument to the DisplayFor helper.
UPDATE:
According to your comment you are not trying to modify the markup but only the value. That's what the second argument of the LabelFor helper could be used for:
#Html.LabelFor(x => x.Foo, Model.Key)
#Html.EditorFor(x => x.Foo)
This creates a label which is associated with the Foo input (for attribute of the label properly assigned) but the text shown is that of the Key property on your view model.

There is no support for creating a template for a specific HTML Helper method (LabelFor).
You could:
Markup your model using meta descriptors to change what value gets displayed as part of the label:
[DisplayName("Custom Label")]
public string Test {get;set;}
You could create your own custom HTML Helper method for rending out a label:
How can I override the #Html.LabelFor template?

You can create a DisplayTemplate and access it via template name:
#Html.DisplayFor(x => x.Foo, "label")
And then just create a template called label.cshtml in your DisplayTemplates folder.
To simplify this call, you can write an extension method that handles this call:
public static MvcHtmlString TemplateLabelFor<TModel, TProperty>(this HtmlHelper<TModel> html, Expression<Func<TModel, TProperty>> property)
{
return html.DisplayFor(property, "label");
}

Related

How to create and implement a custom datatype in mvc3 razor

I googled the problem too many times. But I couldnt find any solution to do this.
I want to create a custom DataType with a default EditorTemplate and DisplayTemplate for use in mvc3 razor.
Model
[DataType("MyCustomDataType")]
public MyType Property { get; set; }
// I mean by MyType any type of data: string, int, datetime and so on
View - Razor
#Html.DisplayFor(m => m.Property)
//or
#Html.EditorFor(m => m.Property)
Actually I want to create a reuseable datatype with default editor-template and display-template.
Do you have any suggestion please? Can you give me a useful link or if you can, a simple example please? Thanks in advance.
this is an excellent tutorial for custom editor/display template. Although its not in razor syntax, its easily convertible.
If you want to create editor template depending on Datatype attribute, you can get the attribute value using ViewData.ModelMetadata.AdditionalValues["DataTypeAttribute"]
If the value is your custom datatype value, do what ever you want. Otherwise, do the default.
Not sure if it is a good idea. But it should work.
You can create a new type, i.e. a Person class that you can include in the model that you send to the view. i.e. Model.Person.
By defining a new EditorTemplate and DisplayTemplate with the name Person. By default, calling #Html.EditorTemplateFor(x=>x.Person); will look for a EditorTemplate for the type.
Have a look at the following stackoverflow post on "How to use asp.net mvc Editor Templates"

Is it possible to use a custom html helper editor template without tying it to the model?

So normally I am doing something like this:
#Html.EditorFor(m => m.MyDateTime)
Then I have a custom template DateTime.cshtml that is used as the editor.
Whatever the date value of Model.MyDateTime is will be displayed as expected, and as expected the name of the field on the next POST will be MyDateTime.
My desire is to use the custom template in the Html.EditorFor WITHOUT binding in the model object, instead I wish to give it a form field name to be POSTed but have it start out blank.
However I can't find an override of Html.EditorFor() that will allow me to not specify a model object, so I can only specify the template to use and the html form field name so it starts empty.
Note: I tried #Html.EditorForModel("DateTime", "MyDateTime") but just got an error so I think that I misunderstood what that is for.
(I know I could just have MyDateTime be null coming back from the controller but that is not what I am asking here.)
Why would you want to use an EditFor that is going to edit nothing (no model passed)? Instead of going down that road, you should probably look at using a View or PartialView which do not require having a Strongly-Typed model.

MVC3 View Inheritance not possible?

I want to create an abstract base view (with lots of virtual methods with cshtml)
and then create a derived view that optionally overrides these methods to customise the view:
for example:
override void Header(string title) {
<div class="massive">#title</div>
}
How can this be achieved with razor?
(doesn't everybody want/need to do this?)
I believe you would be better off using Helper methods than trying for an inheritance model on views. Use Scott Gu's blog for an introduction:
http://weblogs.asp.net/scottgu/archive/2011/05/12/asp-net-mvc-3-and-the-helper-syntax-within-razor.aspx
http://www.asp.net/mvc/tutorials/creating-custom-html-helpers-cs
It doesn't quite work like that out of the box, although I'm sure with some effort you could get that to work.
Instead, you create Layouts with defined Sections and then derive other Layouts from those adding new sections if you need to. Then, a view will declare which layout it is using via
#{
Layout = "_Layout.cshtml" // app relative path to layout
}
and can provide markup for any sections as needed using
#section SectionName {
<p>I'm markup to go into a section in the layout this view is using</p>
}
You can pass data via ViewData and/or ViewBag, so you could use them to pass delegates if you wanted to do that.
Alternatively, you might decide add extension methods to HtmlHelper, UrlHelper or even create a WebViewPage derived from System.Web.Mvc.WebViewPage and add any additional properties/methods onto your derived type then set it as the pageBaseType in the <system.web.webPages.razor> in the web.config used by the views.
Simply use sections and layouts. You would define a layout containing some default contents into sections which could be overridden in child views. You could use the IsSectionDefined method in the layout to test whether a child view overrides this section and if not provide default content.
The cleanest way I found is to use a #helper declared in App_Code
which takes delegates as arguments:
#helper Example(Func<int, HelperResult> fn1, Func<int, HelperResult> fn2) {
<div>#fn1(100)</div>
<div>#fn2(200)</div>
}
and then create a view with helper functions:
#helper Custom1(int x) { <span class="small">#x</span> }
#helper Custom2(int x) { <span class="big">#x</span> }
and then invoke shared helper like this:
#Example(Custom1, Custom2)
and, if required, the shared helper can implement a default behaviour if the delegate is null
this is much messier than simply implementing a derived view with a few overriden virtual helpers - but at least it works, is strongly typed, and doesn't use dynamic

What is the #Html.DisplayFor syntax for?

I understand that in Razor, #Html does a bunch of neat things, like generate HTML for links, inputs, etc.
But I don't get the DisplayFor function...
Why would I write:
#Html.DisplayFor(model => model.Title)
when I could just write:
#Model.Title
Html.DisplayFor() will render the DisplayTemplate that matches the property's type.
If it can't find any, I suppose it invokes .ToString().
If you don't know about display templates, they're partial views that can be put in a DisplayTemplates folder inside the view folder associated to a controller.
Example:
If you create a view named String.cshtml inside the DisplayTemplates folder of your views folder (e.g Home, or Shared) with the following code:
#model string
#if (string.IsNullOrEmpty(Model)) {
<strong>Null string</strong>
}
else {
#Model
}
Then #Html.DisplayFor(model => model.Title) (assuming that Title is a string) will use the template and display <strong>Null string</strong> if the string is null, or empty.
I think the main benefit would be when you define your own Display Templates, or use Data annotations.
So for example if your title was a date, you could define
[DisplayFormat(DataFormatString = "{0:d}")]
and then on every page it would display the value in a consistent manner. Otherwise you may have to customise the display on multiple pages. So it does not help much for plain strings, but it does help for currencies, dates, emails, urls, etc.
For example instead of an email address being a plain string it could show up as a link:
#ViewData.TemplateInfo.FormattedModelValue
DisplayFor is also useful for templating. You could write a template for your Model, and do something like this:
#Html.DisplayFor(m => m)
Similar to #Html.EditorFor(m => m). It's useful for the DRY principal so that you don't have to write the same display logic over and over for the same Model.
Take a look at this blog on MVC2 templates. It's still very applicable to MVC3:
http://www.dalsoft.co.uk/blog/index.php/2010/04/26/mvc-2-templates/
It's also useful if your Model has a Data annotation. For instance, if the property on the model is decorated with the EmailAddress data annotation, DisplayFor will render it as a mailto: link.
In general if it is used for just one property it appears that the generated HTML is the same.
For example this code
<td>#Html.DisplayFor(modelItem=>item.Genre.Name)</td>
<td>#item.Genre.Name, This is direct from Item</td>
generates this HTML
<td>myClassNameProperty</td>
<td>myClassNameProperty, This is direct from Item</td>
At the same time now if i want to display all properties in one statement for my class "Genre" in this case,
i can use #Html.DisplayFor() to save on my typing, for least
i can write #Html.DisplayFor(modelItem=>item.Genre) in place of writing a separate statement for each property of Genre as below
#item.Genre.Name
#item.Genre.Id
#item.Genre.Description
and so on depending on number of properties.
3rd party edit
From html-helpers documentation:
An HTML Helper is just a method that returns a string. The string can
represent any type of content that you want. For example, you can use
HTML Helpers to render standard HTML tags like HTML and
tags. You also can use HTML Helpers to render more complex content
such as a tab strip or an HTML table of database data.
To render more complex html mvc custom html templates or custom tag helpers in asp.net core are used.
Would like to elaborate with a scenario on the reason to use DisplayFor rather than simply using the model value.
The application/significance of what others have mentioned that "DisplayFor uses display template to render", is for example for a boolean, this displays a checkbox
#Html.DisplayFor(model => model.IsBooleanTrue)
Sidenote: EditorFor would display the same checkbox that is not disabled
Documentation: https://learn.microsoft.com/en-us/dotnet/api/system.web.mvc.html.displayextensions.displayfor?view=aspnet-mvc-5.2 (no examples in there unfortunately)
The main difference between #Html.DisplayFor(model => model.Title) and #Model.Title
Html.DisplayFor() is a strongly typed method that can be used to display the value of a model property in a view. It is used to display the value of the property in a way that is appropriate for the data type of the property. It will also respect any DataAnnotations attributes applied to the property and display the property accordingly.
#Model.Title directly outputs the value of the "Title" property to the view. It does not use any formatting or data annotation attribute to display the value.
In summary,
#Html.DisplayFor(model => model.Title) is a more robust and safe way to display a property, since it takes care of formatting and validation, while #Model.Title is a simple and quick way to output a property value.

MVC 3 Shared Template Editor: Set default value for Create but not Edit

I would like to set the default value for an 'EditorFor' on my Shared Template, but only on the Crate method and not the Edit method. How would I do this?
Thanks,
At the end of the day I decided this should be done in the controller, on my Create/Edit actions.
I'm not exactly sure how you can do this other than setting an EditorFor template and using EditorFor for the Create method, and TextboxFor on the Edit method (or vice versa).
You can still extend TextboxFor with custom CSS if needed, but it will probably not be quite as pretty as EditorFor.
Another option would be to build a TextboxFor razor template (if you're using MVC3 and Razor) and load it in as a #helper { } (still passing the model).
see Scott Gu's post on this one

Resources