ASP.Net Core Views
Views aren't much different to MVC5 (notes)
- _ViewStart.cshtml defines the layout page
- Shared/_Layout.cshtml is the master page, with @RenderBody()
- Razor templates are under controller/page.cshtml structure
Nuget packages
You can use Razor views without any packages.
- "Microsoft.AspNetCore.Mvc.TagHelpers" - adds taghelpers
- "Microsoft.AspNetCore.Tooling.Razor" - adds intellisense in razor.
View Location
Instead of the default folders (controllers, models, views) some people prefer "feature folders", where the project has a folder per feature; controllers live alongside the model and view.
You need to tell MVC where to find the views...
- Implement an IViewLocationExpander, specifically the ExpandViewLocations.
//using Microsoft.AspNet.Mvc.Razor;
public class ChangeViewLocationExpander : IViewLocationExpander
{
public void PopulateValues(ViewLocationExpanderContext context)
{
//NA
}
public IEnumerable<string> ExpandViewLocations(
ViewLocationExpanderContext context,
IEnumerable<string> viewLocations)
{
//find the views in "Modules"
return viewLocations.Select(v => v.Replace("/Views", "/Modules"));
}
} - In Startup.ConfigureServices after the AddMvc()
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.Configure<RazorViewEngineOptions>(options =>
options.ViewLocationExpanders.Add(new ChangeViewLocationExpander()));
Injecting services
You should be populating your view model (or ViewBag) with all the data for the page. We can now inject services into the view (which uses dependency injection). This sounds like the wrong thing to do, but at least one scenario (localization) it makes sense.
TagHelpers
- HtmlHelpers (@Html.TextBox) still exist
- Taghelpers are server-side html extensions (they look like client side Angular directives)- the cshtml is more HTML-like and less C# code
- They aren't webforms controls- you can have several taghelpers on the same element - but some helpers write large chunks of code and even javascript (script asp-fallback-src)
- docs.asp.net - source
Instead of @Html.ActionLink("Log in", "Account", "Login"), use a taghelper (and it's easier to add a class or other attributes)
<a asp-controller="Account" asp-action="Login">Log in</a>
The code-like @using (Html.BeginForm()) becomes much nicer
<form asp-controller="Product" asp-action="Update" method="post" class="bootstrappy-stuff" role="form">
<input asp-for="@product.ProductName" type="text" />
<input asp-for="@product.ProductId" type="text" />
<input type="submit" class="btn btn-default" value="Update" title="Update @account.ProductName to new value" />
</form>
- form, a
- asp-controller
- asp-action
- asp-antiforgery
- input
- asp-for - sets value (if type isn't specified, it is set based on the model datatype/DataAnnotation)
- asp-format - format the value
- select
- asp-for
- asp-items - a list of SelectListItem (to get value and text)
- label
- asp-for
- Others
- asp-validation-summary - add to a div
- asp-validation-for - equivalent to Html.ValidationMessageFor
- <environment names="Development"> - basically an @if(IHostingEnvironment.EnvironmentName = "x") {} without having to inject the IHostingEnvironment
In _layout.cshtml
<environment names="Development">
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
</environment>
To run the taghelpers, you need a Views/_ViewImports.cshtml. This is a magic file (like _ViewStart.cshtml which indicates the layout page, Shared/_Layout.cshtml).
@using MyProject
@using MyProject.Models
@using Microsoft.AspNet.Identity
@addTagHelper "*, Microsoft.AspNet.Mvc.TagHelpers"
Add an additional @addTagHelper line for other assemblies containing taghelpers.
You can "escape" taghelpers by adding a ! prefix to the html-element- <!a asp-controller="Account" /> would send write an <a> element with the asp-controller attribute to the browser.