Razor
alternative view engines: default (razor) | custom (spark, nvelocity, brail, bellevue) |
evolution
version | features |
---|---|
3 | engine introduced |
4 | bundling, minification, mobile enhancements? |
core | view components (in place of child actions), tag helpers, html helper changes |
js
angular | react | polymer | knockout | ember | meteor | vue | aurelia |
@Scripts.Render
, @Styles.Render
pointing to resource bundles which are no longer supported.
environment tags to include resources conditionally.
<environment names="development">
<script asp-src-include="/lib/jquery/dist/**/*.js" asp-src-exclude="**.min.js"></script>
</environment>
<environment names="staging, production">
<script asp-src-include="/lib/jquery/dist/**/*.min.js"></script>
</environment>
structure
Views/Shared not specific to single controller _ViewImports.cshtml namespaces for view files and tag helpers _ViewStart.cshtml default layout for the razor view engine
key value
ViewData
: pass data from one controller to correponding view. Init to ViewDataDictionary
. provide access to model binding data.
TempData
: pass data from one controller to another. dictionary derived from TempDataDictionary
class.
ViewBag
sets and gets value dynamically. dynamic property. Available for current requests only, like ViewData
. If redirection occurs its value becomes null.
html helpers
@Html.ActionLink
link text, action & controller names-
strongly vs loosely typed html form helpers: @Html
[TextBox
CheckBox
RadioButton
DropDownList
TextArea
][For
] @using (Html.BeginForm(method, controller, FormMethod.Post))
- display name attribute localization, annotations with resource
@Html.ValidationMessageFor
with a model property lambda and optionally a custom error message@Html.ValidationSummary()
renders model and optionally property level errors, seeexcludePropertyErrors
- @Html.HiddenFor for
input type="hidden"
sections
@RenderBody()
@if (IsSectionDefined("Footer"))
{
@RenderSection("Footer")
}
@section Footer { }
model binding
client validation
data-val-required
anddata-val-email
. Either use them directly in the razor markup- or decorate your view model classes with validation attributes like
[Required]
,[EmailAddress]
,[MaxLength]
,[RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$")]
for a rating regex,[StringLength(60, MinimumLength = 3)]
,[DataType(DataType.Currency)]
,Range
. In the markup use html helpers only. - explicit date format
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
- friendly display name
[Display(Name = "Last Name")]
[DataType(DataType.Date)] string Date {get;}
- jQuery validation and the browser validation can both operate on the form, which is just confusing to the user. To avoid this problem, you can add the
novalidate
attribute to theform
element. - The MVC client-validation features are built on top of the jQuery Validation library. If you prefer, you can use the Validation library directly and ignore the MVC features.
- The term unobtrusive means that validation rules are expressed using attributes added to the HTML elements that views generate.
- Client-side validation is focused on validating individual properties. In fact, it is hard to set up model level client-side validation using the built-in support that comes with MVC. To that end, most MVC applications use client-side validation for property-level issues and rely on server-side validation for the overall model
- razor markup
<input asp-for="ClientName" class="form-control" />
. tag helper transform input elements, inspects attributes on cs model classes, and add html attributes like<input class="form-control" type="text" data-val="true" data-val-required="The name field is required." id="ClientName" name="ClientName" value="" />
. - The JavaScript code looks for elements with the
data-val
attribute and performs local validation in the browser when the user submits the form, without sending an HTTP request to the server. submitting the form results in validation error messages displayed even though no HTTP request is sent to the server. - if you want to use client-side validation, you need to stick to the built-in attributes
server validation
- either remove javascript jquery import
- or perform remote validation on the server through a ajax request. illusion of client side validation. use
[Remote(actionName, controllerName)]
on the view model. method should returnJson()
. Remote validation won’t work without js includes, especially unobtrusive. - remote validation is performed in the background and unlike server-side validation only a subset of properties are validated.
ModelState.GetValidationState(property)
validation errors for specific property- The tag helper adds elements whose values have failed validation to the
input-validation-error
class, which can then be styled to highlight the problem to the user - The model binder has a set of predefined messages that it uses for validation errors. These can be replaced with custom messages by assigning functions to the properties defined by the
IModelBindingMessageProvider
interface.services.AddMvc().AddMvcOptions(opts => opts.ModelBindingMessageProvider.ValueMustNotBeNullAccessor = value => "Please enter a value");
. - The
asp-validation-summary
attribute is applied to a div element, and it displays a list of validation errors when the view is rendered. The value is from an enumeration calledValidationSummary
.<div asp-validation-summary="ModelOnly" class="text-danger"></div>
. public class CustomPropertyValidationAttribute : Attribute, IModelValidator
partial views
no associated actoin model. data sent by parent view.
<div id = "widgets">
<div class = "widget-container">
@Html.Partial ("FeedbackWidget")
</div>
<div class = "widget-container">
@Html.Partial ("TagCloud", tagModel)
</div>
</div>
view components
- inherit from
ViewComponent
base class ViewComponent
class suffix- use an attribute on the class
@await Component.InvokeAsync("XVC")
- not a direct replacement for child actions, not backed by amy action method
- child action:
Views/Shared/{ViewName}
- view component:
Views/Shared/Components/{ComponentName}/{ViewName}
. Component name is class name, view name isDefault.cshtml
. - e.g. param overload
async Task<IViewComponentResult> InvokeAsync(int threshold=10)
tag helpers
- lightweight attribute syntax that looks like html
- input asp-for, link asp-href-include, span asp-validation-for, form asp-controller asp-action
- div asp-validation-summary=”ModelOnly” needs property level validation for each filed
- the way forward compared to html helpers
- custom tag helper can be an attribute or html element
- inherit from
TagHelper
- implement
Process (TagHelperContext context, TagHelperOutput output)
theming
ThemeExpander : IViewLocationExpander
services.Configure<razorViewEngineOptions>(opts => {
opts.ViewLocationExpanders.Clear();
opts.ViewLocationExpanders.Add(new ThemeExpander());
});
- instead of
Views
folder, useThemes
withDefault
andAlternate
subfolders. RazorPage<TModel>
- custom editor/view templates
Shared\EditorTemplates\Date.cshtml