ASP.NET Core MVC视图(指令)

1.创建视图

右键单击Views文件夹-添加–新建文件夹-名称复数Movies

右键单击刚刚新建的Views/Movies文件夹-添加新建项-选择合适的视图选项-名称Index.cshtml–添加。

2.View()帮助方法

public IActionResult About()
{
    ViewData["Message"] = "Your application description page.";

    return View();
}
//隐式返回视图,隐式传递或不传递模型对象
return View();
//隐式返回视图,显式传递模型对象
return View(Orders);

//显式返回视图,隐式传递或不传递模型对象
return View("Orders");
//显式返回视图,显式传递模型对象
return View("Orders", Orders);

2.1视图发现

/Areas/<Area-Name>/Views/<Controller-Name>/<Action-Name>.cshtml
/Areas/<Area-Name>/Views/Shared/<Action-Name>.cshtml
/Views/Shared/<Action-Name>.cshtml
/Pages/Shared/<Action-Name>.cshtml

3.强类型数据 (viewmodel)

在控制器和视图之间传递数据的模型通常称为 viewmodel。

一般情况下,viewmodelPlain Old CLR Object (POCO),含有少量或没有已定义的行为(方法)。通常,viewmodel 类要么存储在 Models 文件夹中,要么存储在应用根目录处的单独 ViewModels 文件夹中。

控制器操作通过View()帮助方法显式将viewmodel类型的实例传递给此操作的视图。

视图文件中@model 指令用于定义viewmodel的类型,@Model 指令用于使用viewmodel类型的实例。

namespace WebApplication1.ViewModels
{
    public class Address
    {
        public string Name { get; set; }
        public string Street { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string PostalCode { get; set; }
    }
}
public IActionResult Contact()
{
    ViewData["Message"] = "Your contact page.";

    var viewModel = new Address()
    {
        Name = "Microsoft",
        Street = "One Microsoft Way",
        City = "Redmond",
        State = "WA",
        PostalCode = "98052-6399"
    };

    return View(viewModel);
}
@model WebApplication1.ViewModels.Address

<h2>Contact</h2>
<address>
    @Model.Street<br>
    @Model.City, @Model.State @Model.PostalCode<br>
    <abbr title="Phone">P:</abbr> 425.555.0100
</address>

4.弱类型数据

在…之间传递数据示例
控制器和视图用数据填充下拉列表。
视图和布局视图从视图文件设置布局视图中的 <title> 元素内容。
分部视图和视图基于用户请求的网页显示数据的小组件。

4.1 ViewData

ViewData 是通过 string 键访问的 ViewDataDictionary 对象。

ViewData通过View()帮助方法传递数据时,是隐式地传递数据。

public IActionResult SomeAction()
{
    ViewData["Greeting"] = "Hello";
    ViewData["Address"]  = new Address()
    {
        Name = "Steve",
        Street = "123 Main St",
        City = "Hudson",
        State = "OH",
        PostalCode = "44236"
    };

    return View();
}
@{
    // Since Address isn't a string, it requires a cast.
    var address = ViewData["Address"] as Address;
}

@ViewData["Greeting"] World!

<address>
    @address.Name<br>
    @address.Street<br>
    @address.City, @address.State @address.PostalCode
</address>

4.2 [ViewData]特性

使用 ViewDataDictionary 的另一种方法是 ViewDataAttribute

使用 [ViewData] 特性的控制器属性将其值存储在字典中并从中进行加载。

public class HomeController : Controller
{
    [ViewData]
    public string Title { get; set; }

    public IActionResult About()
    {
        Title = "About Us";
        ViewData["Message"] = "Your application description page.";

        return View();
    }
}
<!DOCTYPE html>
<html lang="en">
<head>
    <title>@ViewData["Title"] - WebApplication</title>
    ...

4.3 ViewBag

ViewBagMicrosoft.AspNetCore.Mvc.ViewFeatures.Internal.DynamicViewData 对象,可提供对存储在 ViewData 中对象的动态访问权限。

ViewBag 不需要强制转换,因此使用起来更加方便。

public IActionResult SomeAction()
{
    ViewBag.Greeting = "Hello";
    ViewBag.Address  = new Address()
    {
        Name = "Steve",
        Street = "123 Main St",
        City = "Hudson",
        State = "OH",
        PostalCode = "44236"
    };

    return View();
}
@ViewBag.Greeting World!

<address>
    @ViewBag.Address.Name<br>
    @ViewBag.Address.Street<br>
    @ViewBag.Address.City, @ViewBag.Address.State @ViewBag.Address.PostalCode
</address>

5.布局(Layout)视图

5.1布局

按照约定,ASP.NET Core 应用的默认布局名为 _Layout.cshtml

应用可以没有布局,也可以定义多个布局,其中不同的视图指定不同的布局。

//占位
@RenderBody()

5.2 _ViewStart.cshtml

_ViewStart.cshtml 文件通常放置在Views文件夹中。

需要在每个视图之前运行的代码应放在 _ViewStart.cshtml 文件中。

通过在_ViewStart.cshtml文件中设置Layout属性来指定所有视图都将使用 _Layout.cshtml 布局。

@{
    Layout = "_Layout";
}

5.3 _ViewImports.cshtml

_ViewImports.cshtml文件通常放置在Views文件夹中。

可在_ViewImports.cshtml 文件中指定由许多视图共享的Razor指令,这些指令用来导入命名空间和使用依赖注入。

  • @addTagHelper
  • @removeTagHelper
  • @tagHelperPrefix
  • @using
  • @model
  • @inherits
  • @inject
  • @namespace

5.4内容根目录和Web根目录

内容根目录{content root}默认为项目的根目录。

Web 根目录路径默认为 {content root}/wwwroot

Razor.cshtml 文件中,~/ 指向 Web 根目录。

但是,在分部视图中,以波形符斜杠 (~/) 或斜杠 (/) 开头的路径指向项目的根目录。

5.5CSS 隔离

若要为 .cshtml 视图文件添加限定范围的 CSS 样式,请将 CSS 样式置于与 .cshtml 视图文件同目录且名称相同的 .cshtml.css 文件中。 比如,Index.cshtml.css 文件只应用于 Index.cshtml 视图文件的 CSS 样式。

重写的 CSS 样式作为静态资产 {APP ASSEMBLY}.styles.css 进行捆绑和生成。占位符 {APP ASSEMBLY} 是项目名称。指向捆绑 CSS 样式的链接放置在应用的布局中。

<link rel="stylesheet" href="{APP ASSEMBLY}.styles.css" />

5.6节(Section)

布局可以通过调用 RenderSection 来选择引用一个或多个节。节提供一种方法来组织某些页面元素应当放置的位置。required指定此节是必需还是可选的。

//布局视图文件(同步)
@RenderSection("Scripts", required: false)
//布局视图文件(异步)
@await RenderSectionAsync("Scripts", required: false)
//视图文件调用分部视图(异步HTML帮助程序)
@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
//视图文件调用分部视图(分部标记帮助程序)
@section Scripts {
    <partial name="_ValidationScriptsPartial" />
}
//视图文件直接调用
@section Scripts {
     <script type="text/javascript" src="~/scripts/main.js"></script>
}

6.分部(Partial)视图

分部视图的文件名通常以下划线 (_) 开头,名称中带Partial字符的.cshtml文件。

有两种方法可引用分部视图:分布标记帮助程序(Partial Tag Helper)和异步 HTML 帮助程序(Asynchronous HTML Helper)。

6.1分部标记帮助程序

分部标帮助程序会异步呈现内容并使用类似 HTML 的语法:

<partial name="_PartialName" />

6.2 for属性

使用 for 属性,将模型传递给分部视图进行绑定。

<partial name="_ProductPartial" for="Product">
using Microsoft.AspNetCore.Mvc.RazorPages;
using TagHelpersBuiltIn.Models;

namespace TagHelpersBuiltIn.Pages
{
    public class ProductModel : PageModel
    {
        public Product Product { get; set; }

        public void OnGet()
        {
            Product = new Product
            {
                Number = 1,
                Name = "Test product",
                Description = "This is a test product"
            };
        }
    }
}

6.3model属性

model 属性分配模型实例,以传递到分部视图。特性 model 不能与 for 特性一起使用。

<partial name="_ProductPartial"
         model='new Product { Number = 1, Name = "Test product", Description = "This is a test" }'>
//HTML帮助程序
//product是Product的实例
@await Html.PartialAsync("_ProductPartial", product)

6.4view-data属性

view-data 属性分配 ViewDataDictionary 以传递给分部视图。

@{
    ViewData["IsNumberReadOnly"] = true;
}

<partial name="_ProductViewDataPartial" for="Product" view-data="ViewData">

6.5异步HTML帮助程序

使用异步HTML帮助程序时,可以使用PartialAsync方法,前面需要@await修饰。

@await Html.PartialAsync("_PartialName")

另外,使用异步HTML帮助程序时,还可以使用RenderPartialAsync方法,前面需要@{ await }修饰。

由于 RenderPartialAsync 流式传输呈现的内容,因此在某些情况下它可提供更好的性能。

@{
    await Html.RenderPartialAsync("_AuthorPartial");
}

6.6分部视图发现

如果按名称(无文件扩展名)引用分部视图,则按所述顺序搜索以下位置:

/Areas/<Area-Name>/Views/<Controller-Name>
/Areas/<Area-Name>/Views/Shared
/Views/Shared
/Pages/Shared

7.Razor语法

Razor语法 是一种标记语法(以 @ 符号开头),用于将基于 .NET 的代码嵌入到HTML网页中。

Razor语法通常用于 .cshtml 文件 和 .razor组件文件。

7.1注释

//C#注释和HTML注释
@{
    /* C# comment */
    // Another C# comment
}
<!-- HTML comment -->
//Razor注释
@*
    @{
        /* C# comment */
        // Another C# comment
    }
    <!-- HTML comment -->
*@

7.2转义字符

//转义@符号
<p>@@Username</p>

//转义Razor关键字
@(functions)

//转义C# Razor关键字
@(@case)

//邮件的@符号不会被认为转义字符
<a href="mailto:Support@contoso.com">Support@contoso.com</a>

7.3隐式Razor表达式

//隐式Razor以@开头,后跟C#代码
@DateTime.Now
//隐式Razor不能包含空格,但await除外
<p>@await DoSomething("hello", "world")</p>
//隐式Razor不能包含C#泛型,因为<>字符会被解释为HTML标记。
<p>@GenericMethod<int>()</p>

7.4显式Razor表达式

//显式Razor由@符号和圆括号组成
//显式Razor可以包含空格
<p>Last week this time: @(DateTime.Now - TimeSpan.FromDays(7))</p>
//显式Razor可以包含C#泛型
<p>@(GenericMethod<int>())</p>
//如果不使用显式表达式,<p>Age@joe.Age</p>会被视为电子邮件地址
@{
    var joe = new Person("Joe", 33);
}
<p>Age@(joe.Age)</p>

7.5表达式编码

计算结果为字符串的 C# 表达式采用 HTML 编码。 计算结果为 IHtmlContent 的 C# 表达式直接通过 IHtmlContent.WriteTo 呈现。 计算结果不为 IHtmlContent 的 C# 表达式通过 ToString 转换为字符串,并在呈现前进行编码。

@("<span>Hello World</span>")

//被HTML编码后
&lt;span&gt;Hello World&lt;/span&gt;
//最终在浏览器中显式为纯文本
<span>Hello World</span>

对未经审查的用户输入使用 HtmlHelper.Raw 会带来安全风险。用户输入可能包含恶意的 JavaScript 或其他攻击。审查用户输入比较困难。应避免对用户输入使用 HtmlHelper.Raw,非用户输入可以使用HtmlHelper.Raw

@Html.Raw("<span>Hello World</span>")

//最终<span>会被作为html标签呈现
<span>Hello World</span>

7.6Razor代码块

Razor 代码块以 @ 开始,并括在 {} 中。

表达式与代码块的共同点是:里面带HTML标签的HTML都会被呈现,HTML编码除外。区别在于:表达式里面的C#代码会被呈现,而代码块里面的C#代码不会被呈现。

//一个视图中的代码块和表达式共享相同的作用域并按顺序进行定义
@{
    var quote = "The future depends on what you do today. - Mahatma Gandhi";
}

<p>@quote</p>

@{
    quote = "Hate cannot drive out hate, only love can do that. - Martin Luther King, Jr.";
}

<p>@quote</p>

//输出
<p>The future depends on what you do today. - Mahatma Gandhi</p>
<p>Hate cannot drive out hate, only love can do that. - Martin Luther King, Jr.</p>
@{
    var inCSharp = true;
    <p>Now in HTML, was in C# @inCSharp</p>
}

//输出
<p>Now in HTML, was in C# True</p>
//本地函数
@{
    void RenderName(string name)
    {
        <p>Name: <strong>@name</strong></p>
    }

    RenderName("Mahatma Gandhi");
    RenderName("Martin Luther King, Jr.");
}

//输出
<p>Name: <strong>Mahatma Gandhi</strong></p>
<p>Name: <strong>Martin Luther King, Jr.</strong></p>
//如果没有HTML或Razor标记,则会发生Razor运行时错误,可以使用<text>标签输出不带HTML标签的HTML。
//仅呈现<text>标记之间的内容,内容之间仅显式一个空格,多余的空格以及<text></text>标记之前或之后的空格都不会显示在HTML输出中。
//<text>标签内的html标签会被作为html标签呈现
@{
    <text>  Hello   World   </text>
}

//输出
Hello World
//另外还可以使用@:符号输出整个行中除了@:符号以外的后面的不带HTML标签的HTML。
//@:内的html标签会被作为html标签呈现
//与<text>标签的区别在于@:仅支持单行内容,<text>标签支持多行内容
@{
    @:  Hello   World
}

//输出
Hello World

7.7 @lock语句

@lock (SomeLock)
{
    // Do critical section work
}

7.8 @using语句

@using (Html.BeginForm())
{
    <div>
        Email: <input type="email" id="Email" value="">
        <button>Register</button>
    </div>
}

7.9条件语句@if, else if, else, and @switch

@if (value % 2 == 0)
{
    <p>The value was even.</p>
}
//else 和 else if 不需要 @ 符号。
@if (value % 2 == 0)
{
    <p>The value was even.</p>
}
else if (value >= 1337)
{
    <p>The value is large.</p>
}
else
{
    <p>The value is odd and small.</p>
}
@switch (value)
{
    case 1:
        <p>The value is 1!</p>
        break;
    case 1337:
        <p>Your number is 1337!</p>
        break;
    default:
        <p>Your number wasn't 1 or 1337.</p>
        break;
}

7.10迭代语句@for, @foreach, @while, and @do while

@{
    var people = new Person[]
    {
          new Person("Weston", 33),
          new Person("Johnathon", 41),
          ...
    };
}
@{ var i = 0; }
@while (i < people.Length)
{
    var person = people[i];
    <p>Name: @person.Name</p>
    <p>Age: @person.Age</p>

    i++;
}
@{ var i = 0; }
@do
{
    var person = people[i];
    <p>Name: @person.Name</p>
    <p>Age: @person.Age</p>

    i++;
} while (i < people.Length);
@for (var i = 0; i < people.Length; i++)
{
    var person = people[i];
    <p>Name: @person.Name</p>
    <p>Age: @person.Age</p>
}
@foreach (var person in people)
{
    <p>Name: @person.Name</p>
    <p>Age: @person.Age</p>
}

7.11异常语句@try, catch, finally

@try
{
    throw new InvalidOperationException("You did something invalid.");
}
catch (Exception ex)
{
    <p>The exception message: @ex.Message</p>
}
finally
{
    <p>The finally statement.</p>
}

8.Razor指令

8.1@attribute指令

@attribute 指令将给定的特性添加到生成的视图的类中。

//添加[Authorize]特性
@attribute [Authorize]

8.2@code指令

仅适用于Razor组件(.razor)。

使用一个或多个 @code 代码块,可以将 C# 成员 (字段、属性和方法) 添加到Razor组件。

对于Razor组件,@code@functions 的别名,建议优先使用@code

@code {
    // C# members (fields, properties, and methods)
}

8.3 @functions指令

@functions 指令允许将 C# 成员(字段、属性和方法)添加到生成的类中:

@functions {
    // C# members (fields, properties, and methods)
}
//示例
@functions {
    public string GetHello()
    {
        return "Hello";
    }
}

<div>From method: @GetHello()</div>
//输出
<div>From method: Hello</div>
//生成的 Razor C# 类
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Razor;

public class _Views_Home_Test_cshtml : RazorPage<dynamic>
{
    // Functions placed between here 
    public string GetHello()
    {
        return "Hello";
    }
    // And here.
#pragma warning disable 1998
    public override async Task ExecuteAsync()
    {
        WriteLiteral("\r\n<div>From method: ");
        Write(GetHello());
        WriteLiteral("</div>\r\n");
    }
#pragma warning restore 1998

8.4@implements指令

@implements 指令为生成的类实现接口。

@implements IDisposable

<h1>Example</h1>

@functions {
    private bool _isDisposed;

    ...

    public void Dispose() => _isDisposed = true;
}

8.5@inherits指令

@inherits 指令对视图继承的类提供完全控制:

@inherits TypeNameOfClassToInheritFrom
//自定义Razor page类型
using Microsoft.AspNetCore.Mvc.Razor;

public abstract class CustomRazorPage<TModel> : RazorPage<TModel>
{
    public string CustomText { get; } = 
        "Gardyloo! - A Scottish warning yelled from a window before dumping" +
        "a slop bucket on the street below.";
}
@inherits CustomRazorPage<TModel>

<div>Custom text: @CustomText</div>
//输出
<div>
    Custom text: Gardyloo! - A Scottish warning yelled from a window before dumping
    a slop bucket on the street below.
</div>

@Model@inherits 可在同一视图中使用。

@inherits CustomRazorPage<TModel>

<div>The Login Email: @Model.Email</div>
<div>Custom text: @CustomText</div>

//输出
<div>The Login Email: rick@contoso.com</div>
<div>
    Custom text: Gardyloo! - A Scottish warning yelled from a window before dumping
    a slop bucket on the street below.
</div>

8.6@inject指令

@inject 指令允许 Razor Page将服务从服务容器注入到视图。

8.7@layout指令

仅适用于Razor组件(.razor)。

@layout 指令为具有 @page 指令的可路由 Razor 组件指定布局。 布局组件用于避免代码重复和不一致。

8.8@model指令

适用于 MVC 视图和 Razor Pages (.cshtml)。

@model 指令指定传递到视图的模型类型。

@model TypeNameOfModel

8.9@namespace指令

  • 设置生成的 Razor 页面、MVC 视图或 Razor 组件的类的命名空间。
  • 在目录树、 _ViewImports.cshtml (views or pages) 、_Imports.razor (Razor components)中从最接近的导入文件设置 pages、viewscomponents 类的根派生命名空间。
@namespace Your.Namespace.Here
  • 每页导入 Pages/_ViewImports.cshtml
  • Pages/_ViewImports.cshtml 包含 @namespace Hello.World
  • 每个页面都有 Hello.World,作为其命名空间的根。
PageNamespace
Pages/Index.cshtmlHello.World
Pages/MorePages/Page.cshtmlHello.World.MorePages
Pages/MorePages/EvenMorePages/Page.cshtmlHello.World.MorePages.EvenMorePages

8.10@page指令

@page 指令具有不同的效果,具体取决于其所在文件的类型。 指令:

  • .cshtml 文件中表示该文件是 Razor 页面。
  • 指定 Razor 组件应直接处理请求。

8.11@preservewhitespace指令

仅适用于 Razor 组件 (.razor)。

设置为 false(默认值)时,如果出现以下情况,则会删除来自 Razor 组件 (.razor) 的呈现标记中的空格:

  • 元素中的前导或尾随空白。
  • RenderFragment 参数中的前导或尾随空白。 例如,传递到另一个组件的子内容。
  • 在 C# 代码块(例如 @if@foreach)之前或之后。

8.12@section指令

适用于 MVC 视图和 Razor Pages (.cshtml)。

指令 @section 与 MVC 和 Razor Pages 布局结合使用,使视图或页面能够呈现 HTML 页面不同部分的内容。

8.13@using指令

@using 指令用于向生成的视图添加 C# using 指令。

在 Razor 组件中,@using 还控制哪些组件在范围内。

@using System.IO
@{
    var dir = Directory.GetCurrentDirectory();
}
<p>@dir</p>

9.指令属性

Razor 指令属性由隐式表达式表示,@ 符号后有保留关键字。 指令属性通常会更改元素的分析方式或启用不同的功能。

9.1@attributes属性

仅适用于 Razor 组件 (.razor)。

@attributes 允许组件呈现未声明的属性。

9.2@bind属性

仅适用于 Razor 组件 (.razor)。

组件中的数据绑定通过 @bind 属性实现。

9.3@bind:culture属性

仅适用于 Razor 组件 (.razor)。

@bind:culture 属性与 @bind 属性一起使用以提供 System.Globalization.CultureInfo 用于分析和设置值的格式。

9.4@on{EVENT}属性

仅适用于 Razor 组件 (.razor)。

Razor 为组件提供事件处理功能。

9.5@on{EVENT}:preventDefault属性

仅适用于 Razor 组件 (.razor)。

禁止事件的默认操作。

9.6@on{EVENT}:stopPropagation属性

仅适用于 Razor 组件 (.razor)。

停止事件的事件传播。

9.7@key属性

仅适用于 Razor 组件 (.razor)

@key 指令属性使组件diffing算法保证基于键的值保留元素或组件。

9.8@ref属性

仅适用于 Razor 组件 (.razor)。

组件引用 (@ref) 提供了一种引用组件实例的方法,以便可以向该实例发出命令。

9.9@typeparam属性

仅适用于 Razor 组件 (.razor)。

@typeparam 指令声明生成的组件类的泛型类型参数:

@typeparam TEntity

支持具有 where 类型约束的泛型类型:

@typeparam TEntity where TEntity : IEntity

10.模板化 Razor 委托

通过 Razor 模板,可使用以下格式定义 UI 代码片段:

@<tag>...</tag>

示例一:

public class Pet
{
    public string Name { get; set; }
}
@{
    Func<dynamic, object> petTemplate = @<p>You have a pet named <strong>@item.Name</strong>.</p>;

    var pets = new List<Pet>
    {
        new Pet { Name = "Rin Tin Tin" },
        new Pet { Name = "Mr. Bigglesworth" },
        new Pet { Name = "K-9" }
    };
}
@foreach (var pet in pets)
{
    @petTemplate(pet)
}

//输出
<p>You have a pet named <strong>Rin Tin Tin</strong>.</p>
<p>You have a pet named <strong>Mr. Bigglesworth</strong>.</p>
<p>You have a pet named <strong>K-9</strong>.</p>

示例二:

@using Microsoft.AspNetCore.Html

@functions {
    public static IHtmlContent Repeat(IEnumerable<dynamic> items, int times,
        Func<dynamic, IHtmlContent> template)
    {
        var html = new HtmlContentBuilder();

        foreach (var item in items)
        {
            for (var i = 0; i < times; i++)
            {
                html.AppendHtml(template(item));
            }
        }

        return html;
    }
}
<ul>
    @Repeat(pets, 3, @<li>@item.Name</li>)
</ul>

//输出
<ul>
    <li>Rin Tin Tin</li>
    <li>Rin Tin Tin</li>
    <li>Rin Tin Tin</li>
    <li>Mr. Bigglesworth</li>
    <li>Mr. Bigglesworth</li>
    <li>Mr. Bigglesworth</li>
    <li>K-9</li>
    <li>K-9</li>
    <li>K-9</li>
</ul>
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值