页面组织:PartialView/ChildAction/Editor

ChildAction部分


类似于ASP.NET Core:PartialView,除了:

调用方式

需使用@Html.Partial(),代码如下所示:

@_LogOnStatus.cshtml和当前页面在同一个文件夹,@ @或者_LogOnStatus.cshtml在Shared文件夹下@ @Html.Partial("_LogOnStatus") @将当前Model的Name,传递给_LogOnStatus.cshtml@ @Html.Partial("_LogOnStatus", Model.Name) @将ViewData["Id"]=32,传递给_LogOnStatus.cshtml@ @Html.Partial("_LogOnStatus", new ViewDataDictionary { { "Id", 32 } }) @_LogOnStatus.cshtml在当前页面所在文件夹的子文件夹Yz下@ @或者_LogOnStatus.cshtml在Shared/Yz文件夹下@ @Html.Partial("Yz/_LogOnStatus") @_LogOnStatus.cshtml在~/Views/User/下,注意.cshtml后缀不能省略@ @Html.Partial("~/Views/User/_LogOnStatus.cshtml")


ChildAction部分


类似于:ASP.NET Core:View Component,除了:

调用方式

使用@Html.Action(),比如:

@Html.Action("_Reminder", "Register", new { id = 32 })

其中:

  • Reminder:action name,必填
  • Register:controller name,可选,默认为当前Controller
  • new { id = 32 }:route data,可选,通常使用匿名对象

然后,在上述指定的Controller中,添加一个Action

public PartialViewResult _Reminder(int id) //惯例:片段Html的Action和View都前缀下划线 { return PartialView(); }

通过return PartialView() 返回的是一个部分页面(PartialViewResult),它和普通ViewResult最大的区别是:受_ViewStart.cshtml内容控制(通常是自动引入_Layout)

Action中就可以写需要的后台逻辑,这就是ChildAction和Partial的最大区别!

执行顺序

  1. 首先进入父Action
  2. 父Action执行完成,然后进入View页面执行
  3. 直到@Html.Action()调用进入ChildAction

断点演示:注意route data(id)的传值

[ChildActionOnly]特性

在Action上可以添加 [ChildActionOnly],使其只能被其他View调用,不能独立响应HTTP请求。

换言之,如果没有[ChildActionOnly],该Action就可以被直接调用。

(演示:浏览器输入ChildAction的url访问……)

Filter影响

和RazorPage不同,MVC中的Filter是会影响ChildAction。这给我们带来便利的同事,也带来一些麻烦。

首先是要结合ChildAction的执行顺序明白Filter的执行顺序:

Index()
-- ActionExecuted()
-- ResultExecuting()
@ Index.cshtml
@Html.Action("_Index")
--ActionExecuting()
ChildAction()
--ActionExecuted()
--ResultExecuting()
--ResultExecuted()
-- ResultExecuted()

然后MVC在FilterContext中,为我们提供IsChildAction属性:

if (!filterContext.IsChildAction)

应用详见:ContextPerRequest


Editor部分


如果我们的PartialView或ChildAction包含Form表单内容,对应一个可重用的Model,比如:

namespace ViewModel.Register { public class IndexModel { public InviterModel Inviter { get; set; }

public class InviterModel { public string UserName { get; set; } public string Code { get; set; } }

注册用的IndexModel包含了邀请人相关的InviterModel,相应的View也变成:

@model ViewModel.Register.InviterModel

@Html.TextBoxFor(m => m.UserName)
@Html.TextBoxFor(m => m.Code)

那么,在Register.cshtml页面应该如何调用呢?

如果使用:

PartialView

POST的时候,Register.IndexModel.InviterModel为null值_(断点演示)_

@想一想@:为什么?

ChildAction

POST的时候:

  • 首先进入父Action,且此时Register.IndexModel.InviterModel仍然为null值
  • 此后在子ChildAction时,InviterModel可以有值

但是,注意:

所以,最佳做法是使用:

EditorTemplate

首先,把对应的.cshtml文件(如:Inviter.cshtml)放在:

  • ~/Shared/EditorTemplates文件夹下,或者
  • 父页面所在文件夹的EditorTemplates文件夹下,如 ~/Register/EditorTemplates

然后,在父页面中调用:

@Html.EditorFor(m => m.Inviter, "Inviter")

演示:__EditorFor的三个重载方法

注意参数templateName可以:

  • 省略,这时候MVC默认会在EditorTemplates下寻找和model同名的.cshtml文件做template,比如InviterModel,注意Model后缀
  • 使用绝对路径:

同名的

你可能感兴趣的:(javascript)