ASP.NET Core MVC_00View


代码

View

传递数据到Views

控制器和视图在同一进程中运行。要传递数据,可以使用ViewDataDictionary。ViewData,Key为String,Value为Object。ViewBag是一种动态类型,可以指定任何属性名称以将数据传递给View。

public IActionResult PassingData()
{
    ViewBag.MyData = "Hello from the controller";
    return View();
}
<h2>@ViewBag.MyData</h2>

Razor 语法

在ASP.NET Core MVC 中,可以在View上使用Razor语法写C#代码。

<div>@ViewBag.MyData</div>

@{
string name = "Angela";
}

<div>@name</div>

@foreach(var item in list)
{
    <li>The item name is @item.</li>
}

在某些情况下,无法自动检测C#代码的结尾。可以使用括号解决此问题,如下所示

<div>@(name), Stephanie</div>

创建强类型视图

Controller传递数据给View的另一种方法是传递Model,使用Model可以创建强类型视图。

Controller

public IActionResult PassingAModel() => View(GetSampleData());

private IEnumerable<Menu> GetSampleData() =>
    new List<Menu>
    {
        new Menu
        {
            Id = 1,
            Text = "宫保鸡丁",
            Price = 6.9,
            Category = "Main"
        },
        new Menu
        {
            Id = 2,
            Text = "水煮牛肉",
            Price = 6.9,
            Category = "Main"
        },
         new Menu
        {
            Id = 3,
            Text = "辣炒蛤蜊",
            Price = 6.9,
            Category = "Main"
        }
    };

View

@using MVCSampleApp.Models
@model IEnumerable<Menu>

<div>
    <ul>
        @foreach (var item in Model)
        {
            <li>@item.Text</li>
        }
    </ul>
</div>

布局

使用VS创建_ViewStart.cshtml——定义所有View是否需要布局页。(在Views目录下创建)

@{
    Layout = "_Layout";
}

如果所有View不需要layout,可以将Layout设为null

@{
	Layout = null;
}

默认布局页

@RenderBody()呈现网页内容

默认布局页

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
</head>
<body>
    <div>
        @RenderBody()
    </div>
</body>
</html>

经过修改的

<!DOCTYPE html>

<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initialscale=1.0" />
    <title>@ViewBag.Title</title>
    <environment include="Development">
        <link rel="stylesheet"
              href="~/lib/bootstrap/dist/css/bootstrap.css" />
        <link rel="stylesheet" href="~/css/site.css" />
    </environment>
    <environment exclude="Development">
        <link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/css/bootstrap.min.css"
              asp-fallbackhref=" ~/lib/bootstrap/dist/css/bootstrap.min.css"
              asp-fallback-test-class="sr-only" asp-fallback-testproperty="position" asp-fallback-test-value="absolute" />
        <link rel="stylesheet" href="~/css/site.min.css" aspappend-version="true" />
    </environment>
    <title>@ViewBag.Title - My ASP.NET Application</title>
</head>
<body>
    <div class="container body-content">
        <header>
            <h1>ASP .NET MVC例子</h1>
        </header>
        <nav>
            <ul>
                <li><a asp-controller="ViewsDemo" asp-action="LayoutSample">LayoutSample</a></li>
                <li><a asp-controller="ViewsDemo" asp-action="LayoutUsingSections">Layout Using Sections</a></li>
            </ul>
        </nav>
        <div>
            @RenderBody()
        </div>
        <hr />
        <footer>
            <p>
                <div>Sample Code for Professional C#</div> @DateTime.Now.Year - My ASP.NET Application
            </p>
        </footer>
    </div>
</body>
</html>

添加LayoutSample页面

@{
    ViewData["Title"] = "LayoutSample";
}
<h2>LayoutSample</h2>

结果
这里写图片描述

Sections

使用Sections,在View的某个位置上添加内容。

以下代码段使用名为PageNavigation的Section。 默认情况下需要此section,如果section未定义,则加载视图将失败。 当required参数设置为false时,section变为可选

<!–– ... ––>
<div>
	@RenderSection("PageNavigation", required: false)
</div>
<div>
@RenderBody()
</div>
<!–– ... ––>

添加LayoutUsingSections页面

@{
    ViewBag.Title = "Layout Using Sections";
} 
<h2>使用Sections的Layout</h2>
<div>这是主要内容</div>
@section PageNavigation
    {
    <div>拥有Navigation的View</div>
    <ul>
        <li>Nav1</li>
        <li>Nav2</li>
    </ul>
}

结果
这里写图片描述

Sections不仅仅在Html中的Body放置内容,还可以应用于head中的一些标签——例如metadata

使用Partial View定义内容

Layout为Web应用程序中的多个页面提供了总体定义,而Partial View是定义视图中的内容。 局部视图没有布局。而且,Partial View和普通View很像,Partial View和普通View有相同的基类,它们都有Model。

现在,从模型开始,该模型包含由EventsAndMenusContext类定义的independent collections,events和menus 的属性。

public class EventsAndMenusContext
{
    private IEnumerable<Event> GetEvents() =>
        new List<Event>
        {
            new Event (1, "Formula 1 G.P. Australia, Melbourne", new DateTime(2018, 3, 25)),
            new Event(2, "Formula 1 G.P. Bahrain, Sakhir", new DateTime(2018, 4, 8)),
            new Event(3, "Formula 1 G.P. China, Shanghai", new DateTime(2018, 4, 15)),
            new Event(4, "Formula 1 G.P. Aserbaidschan, Baku", new DateTime(2018, 4, 29))
        };

    private IEnumerable<Menu> GetMenus() =>
        new List<Menu>
        {
            new Menu
            {
                Id=1,
                Text="Baby Back Barbecue Ribs",
                Price=16.9,
                Category="Main"
            },
            new Menu
            {
                Id=2,
                Text="Chicken and Brown Rice Piaf",
                Price=12.9,
                Category="Main"
            },
            new Menu
            {
                Id=3,
                Text="Chicken Miso Soup with Shiitake Mushrooms",
                Price=6.9,
                Category="Soup"
            }
        };

    private IEnumerable<Event> _events = null;
    public IEnumerable<Event> Events
    {
        get => _events ?? (_events = GetEvents());
    }

    private IEnumerable<Menu> _menus = null;
    public IEnumerable<Menu> Menus
    {
        get => _menus ?? (_menus = GetMenus());
    }
}

为了让控制器构造函数注入类型,需要在startup类中使用依赖注入注册EventsAndMenusContext类。

在服务端代码使用部分视图

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    ...
    //为了让控制器构造函数注入类型,需要在startup类中使用依赖注入注册EventsAndMenusContext类。
    services.AddScoped<EventsAndMenusContext>();

}

Controller

public IActionResult UseAPartialView1() => View(_context);

View

@using MVCSampleApp.Models
@model EventsAndMenusContext
@{
    ViewBag.Title = "Use a Partial View";
    ViewBag.EventsTitle = "Live Events";
} 
<h2>使用部分视图</h2>
<div>主视图</div>
<div>
    @await Html.PartialAsync("ShowEvents", Model.Events)
</div>

结果
这里写图片描述

可以使用同步方法Html.Partial替代Html.PartialAsync。

在View中呈现partial view的另一种方法是使用HTML Helper方法Html.RenderPartialAsync,该方法被定义为返回Task。 此方法直接将部分视图内容写入响应流。

partial view也支持ViewBag

@using MVCSampleApp.Models
@model IEnumerable<Event>

<h2>@ViewBag.EventsTitle</h2>
<table>
    @foreach (var item in Model)
    {
    <tr>
        <td>@item.Day.ToShortDateString()</td>
        <td>@item.Text</td>
    </tr>
    }
</table>

返回部分视图

部分视图可以通过控制器返回
Controller

public ActionResult UseAPartialView2() => View();
public ActionResult ShowEvents()
{
    ViewBag.EventsTitle = "Live Events";
    return PartialView(_context.Events);
}

View
利用fetch代替Ajax从服务器下载部分视图

@using MVCSampleApp.Models
@model EventsAndMenusContext
@{
    ViewBag.Title = "Use a Partial View";
} 
<script src="~/lib/jquery/dist/jquery.js"></script>
<script>
    (function () {
        window.onload = function () {
            var buttonEvents = document.getElementById("getEvents");
            buttonEvents.onclick = function () {
                if (window.fetch == null) {
                    output.innerHTML = "<div>window.fetch not supported. Use another browser</div>";
                    return;
                }
                //利用fetch代替Ajax从服务器下载部分视图
                var result = fetch("/ViewsDemo/ShowEvents");
                result.then(function (response){
                    return response.text();
                }).then(function (text){
                    var output = document.getElementById("output");
                        output.innerHTML = text;});
            };
        };
    })();
</script>
<h2>使用部分视图</h2>
<div>主页面</div>
<button id="getEvents">加载部分视图按钮</button>
<div id="output">
</div>

结果
这里写图片描述

View Component

ASP.NET Core MVC 提供了部分视图的替代方法:View Component。View Component与Partial View非常相似; 主要区别在于View Component没有Controller。 这使得View Component可以轻松地和多个控制器一起使用。View Component真正有用的地方是菜单的动态导航,登录面板或博客中的侧边栏内容。这些场景对独立的单个控制器非常友好。

与Controller和View一样,View Component有两个部分。对于View Component,ViewComponent(或具有ViewComponent属性的POCO类)派生的类会接管Controller的功能。用户界面的定义与View类似,但调用view component的方法不同。

public class EventListViewComponent : ViewComponent
{
    //需要在Startup中注册的EventsAndMenusContext类型。
    private readonly EventsAndMenusContext _context;
    public EventListViewComponent(EventsAndMenusContext context)
    {
        _context = context;
    }
    /// <summary>
    /// InvokeAsync方法定义为从显示ViewComponent的View中调用。
    /// 此方法可以包含任何数量和类型的参数,因为IViewComponentHelper接口定义的方法使用params关键字定义了灵活数量的参数。
    /// 也可以使用同步实现此方法,返回的是IViewComponentResult。
    /// 最好使用异步,例如访问数据库。
    /// view component需要存储在ViewComponents目录中。 该目录本身可以放在项目中的任何位置
    /// </summary>
    /// <param name="from"></param>
    /// <param name="to"></param>
    /// <returns></returns>
    public Task<IViewComponentResult> InvokeAsync(DateTime from, DateTime to) =>
        Task.FromResult<IViewComponentResult>(View(EventsByDateRange(from, to)));
    private IEnumerable<Event> EventsByDateRange(DateTime from, DateTime to) =>
        _context.Events.Where(e => e.Day >= from && e.Day <= to);
}

View
View Component的View可以使用MVC View Page模板创建。目录要求:Components / [viewcomponent]文件夹中——例如,Components / EventList。
用于特定视图还是用于公共?
要使view component可用于所有控件,需要创建Views/Shared/Components文件夹。
当您仅使用来自一个特定controller的view component时,可以将其放入视图控制器(view Controller)文件夹中。但是,与此视图的不同之处在于它需要命名为default.cshtml。也可以创建其他视图名称; 需要使用InvokeAsync方法返回的View方法的参数指定这些视图。

Views/Shared/Components/EventList/default.cshtml

@using MVCSampleApp.Models;
@model IEnumerable<Event>
<h3>Formula 1 Calendar</h3>
<ul>
    @foreach (var ev in Model)
    {
        <li>
            <div>@ev.Day.ToString("D")</div><div>@ev.Text</div>
        </li>
    }
</ul>

VIew:UseViewComponent1

@{
    ViewBag.Title = "View Components Sample";
} 
<h2>@ViewBag.Title</h2>
<p>
    @*Component是View的动态创建属性(dynamically created property),它返回实现IViewComponentHelper的对象。
    IViewComponentHelper允许调用同步或异步方法
    需要使用Dictionary <string,object>传递参数,其中键与参数名称匹配*@
        @await Component.InvokeAsync("EventList", new
        Dictionary<string, object>()
        {
        ["from"] = new DateTime(2018, 4, 1),
        ["to"] = new DateTime(2018, 4, 20)
        })
</p>

VIew:UseViewComponent2
从ASP.NET Core 1.1开始,就可以使用Tag Helpers调用view component。 Tag Helpers使用类似HTML的代码编写,简化了视图的代码。如果想使用Tag Helpers,需要使用view component所在的程序集的名称添加@addTagHelper指令,才能使用vc标记引用视图组件。在vc标记的冒号之后,跟随视图组件的名称。使用Pascal命名约定定义类时,Tag Helper通过切换为小写字母(而不是大写字母),添加下划线来更改名称; ,因此EventList成为event-list

@addTagHelper *, MVCSampleApp
@{
    ViewBag.Title = "View Components Sample";
} 
<h2>@ViewBag.Title</h2>
<vc:event-list from="@new DateTime(2018, 4, 1)" to="@new DateTime(2018, 4, 20)" />

结果(http://localhost:2253/viewsdemo/UseViewComponent1)
这里写图片描述

在View里使用依赖注入

如果View里直接需要一个service,可以使用关键词inject注入。并且最好使用AddScoped方法注册服务。如前所述,以这种方式注册服务意味着它只对一个HTTP请求实例化一次。 使用AddScoped,在控制器和视图中注入相同的服务,它仅为请求实例化一次。

@using MVCSampleApp.Services
@inject ISampleService sampleService
<p>
    @string.Join(" * ", sampleService.GetSampleStrings())
</p>

对多个View导入命名空间

使用_ViewImports.cshml文件对每个view进行添加using,不必对每个view进行单独添加。

@using MVCSampleApp.Models
@using MVCSampleApp.Services

猜你喜欢

转载自blog.csdn.net/Star_Inori/article/details/82085912