@using 和@namespace 指令在 Razor _ViewImports.cshtml 文件中有什么作用?

What does @using and @namespace directives do in a Razor _ViewImports.cshtml file?

@using@namespace 指令在 Razor _ViewImports.cshtml 文件中的作用是什么?

@using TagHelpersBuiltIn @namespace TagHelpersBuiltIn.Pages @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

_ViewImports.cshtml

无论您在 ViewImports.cshtml 文件中提到使用 @namespace 的什么命名空间,您的视图(.cshtml 文件)都将自动可用,而无需使用 @using。换句话说,它们将隐式可用。如果 ViewImports.cshtml 文件中没有提及,您仍然需要使用 @using.

来自documentation

The @namespace directive was designed so the C# classes added to a project and pages-generated code just work without having to add an @using directive for the code behind file.

换句话说,如果将@namespace添加到_ViewImports.cshtml文件中,那么其他文件将不需要使用@using 在他们每个人中。

什么是_ViewImports.cshtml`?

来自docs:

_ViewImports.cshtml serves one major purpose: to provide namespaces which can be used by all other views. In previous MVC projects, this functionality was provided by the web.config file in the Views folder; since the web.config no longer exists, global namespaces are now provided by this file.

更多说明

在 MVC5 和更早的版本中,如果你检查 Views/web.config 文件,你会注意到 xml 并且在其中你会注意到这个或可能更多 <add 个元素:

<namespaces>
    <add namespace="System.Web.Mvc" />
    <add namespace="System.Web.Mvc.Ajax" />
    <add namespace="System.Web.Mvc.Html" />
    <add namespace="System.Web.Routing" />
    <add namespace="Mvc" />
</namespaces>

这基本上是在指示 Razor 引擎,此特定 Views 文件夹中的所有 .cshtml 文件都需要这些命名空间,因此.cshtml 文件可以使用那些没有 @using 的命名空间。在 MVC6 中,Views/web.config 不再存在,取而代之的是具有相同目的的 ViewImports.cshtml 文件.

好的,那@using 是干什么用的?

您仍然需要 .cshtml 文件中的 @using,用于任何未使用 [=] 中的 @namespace 导入的命名空间87=] 文件。例如,如果您有一个名为 Edit.cshtml 的视图,那么您可能会这样:

@using NamespaceA;

这意味着此命名空间已显式导入以供 Edit.cshmtl 文件使用。 ViewImport.cshtml 文件中提到的一些其他名称空间将自动用于 Edit.cshtml 文件。

ASP.NET核心MVC中的_ViewImports.cshtml文件负责提供可以被其他视图使用或访问的命名空间(即共享命名空间)。

  • @using TagHelpersBuiltIn 标记包含 TagHelpersBuiltIn 父命名空间(即与项目名称相同)。

  • @namespace TagHelpersBuiltIn.Pages 意味着在所有视图中声明命名空间 TagHelpersBuiltIn.Pages,这会启用 cshtml.cs 文件中声明的模型 类(example).

  • @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 指令使 Microsoft.AspNetCore.Mvc.TagHelpers 库内容对所有视图可用,在视图页面中可以使用像 <label asp-for="Model.PropertyName"></label> 这样的标签助手语法。

参考文献:

Tag Helpers in ASP.NET Core

The ViewImports File

什么是_ViewImports.cshtml`?

_ViewImports.cshtml 用于声明驻留在包含 _ViewImports.cshtml 文件的文件夹中的视图的所有导入。它还用于为驻留在该文件夹中的所有视图声明命名空间,此外,还用于声明应该可用于驻留在该文件夹中的视图的任何标签助手。

@namespace

_ViewImports.cshtml 文件中的 @namespace 指令用于声明 Razor Views/Pages 的根命名空间。大多数项目的默认生成 _ViewImports.cshtml 文件将具有 @namespace MyProjectName.Pages。在你的 _ViewImports.cshtml 文件中应该只有一个这样的声明,如果有多个,最后一个将 'win',其余的将无效。 @namespace 指令类似于为 C# class 文件声明命名空间。这只允许为文件夹中的所有视图声明命名空间,而不必在每个视图中声明命名空间。

@using

@using 用于为文件夹内的所有视图添加导入。例如:如果您的 _ViewImports.cshtml 文件包含 @using Microsoft.AspNetCore.Identity,那么该文件夹下的任何视图都可以访问 Microsoft.AspNetCore.Identity 命名空间的成员,而无需通过 @using 显式导入它们指令。

@addTagHelper

@addTagHelper 用于声明所有应可用于包含 _ViewImports.cshtml 文件的文件夹中的视图的标签助手。默认项目模板通常在根 _ViewImports.cshtml 文件中包含以下 @addTagHelper 指令:@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers.

附加信息

需要注意的是,ViewsPages根目录中的_ViewImports.cshtml文件将应用于Views或[=30]的所有子目录=] 文件夹。您还可以在子目录中添加一个 _ViewImports.cshtml 文件,以添加仅应应用于该子目录中的视图的其他 using 语句。还值得注意的是,至少对于 Razor Pages,即使根 _ViewImports.cshtml 文件将命名空间声明为 @namespace MyProject.PagesMyProject\Pages\ASubDirectory 中的视图也会自动获得命名空间 MyProject.Pages.ASubDirectory 而不添加另一个 _ViewImports.cshtml 文件在 MyProject\Pages\ASubDirectory.

中声明命名空间

归因

这个答案最初是对 Coding Yoshi 的答案的编辑。因此,部分答案基于 Coding Yoshi 的答案。

What does @using and @namespace directives do in a Razor _ViewImports.cshtml file?

这是简短的版本:

  • @namespace 为每个 *.cshtml 文件提供一个 适应其目录的命名空间
  • @using 允许每个 *.cshtml 文件访问其命名空间之外的类型
  • _ViewImport 目录和子目录中的所有 .cshtml 个文件受到影响

什么是 C# 命名空间?

  • A namespace 创建范围。在范围内,类型名称必须是唯一的。

  • 在命名空间内部,文件可以无限制地访问命名空间中的所有类型。从命名空间外部,文件只能访问那些具有命名空间限定全名(或使用 using 指令)的类型。

  • 名称空间的存在是为了防止命名冲突:两种类型可以具有相同的名称,只要这些名称位于不同的名称空间中即可。

示例:

namespace Computers {
    // the name Apple must be unique within its namespace
    // from outside its namespace it is Computers.Apple
    public class Apple {} 
}

namespace Garden {
    public class Apple {
        // we access Apple from another namespace via its full name
        public void UseComputer(Computers.Apple appleComputer) { }
    } 
}

什么是 C# using 指令?

使用类型的全名可能不方便。当不存在命名冲突时,using 指令提供了一种从另一个命名空间访问类型的便捷方式 - 无需限定类型的名称。

using Computers;

namespace TechnologyStore {
    // `using Computer` lets us access Apple without qualifying it
    public class SellComputer(Apple appleComputer) { }
}

@namespace@using 如何在 *.cshtml 文件中工作?

*.cshtml 文件也有命名空间和类型。我们可以看到,如果我们将以下代码放入 Razor 页面或视图中。

// Pages/Index.cshtml
@page
<p>@this.GetType().Namespace</p> // AspNetCore
<p>@this.GetType().Name</p> // Pages_Index

// Pages/Foo/Index.cshtml
@page
<p>@this.GetType().Namespace</p> // AspNetCore
<p>@this.GetType().Name</p> // Pages_Foo_Index

*.cshtml 文件的默认命名空间是 AspNetCore。当@model 位于某个自定义命名空间中时,这会很麻烦。如果 @modelMyCustomNamespace 中,那么我们必须做一些工作才能访问它:

// Pages/Index.cshtml
@page
@namespace MyCustomNamespace
@model IndexModel
<p>@this.GetType().Namespace</p> // MyCustomNamespace
<p>@this.GetType().Name</p> // Pages_Index

这不是太多的工作;但是如果我们保持命名空间与我们的目录结构一致,并且如果我们移动 *.cshtml 文件,那么我们将需要更新 @namespace 语句。

// Pages/Foo/Index.cshtml
@page
@namespace MyCustomNamespace.Foo
@model IndexModel
<p>@this.GetType().Namespace</p> // MyCustomNamespace.Foo
<p>@this.GetType().Name</p> // Pages_Foo_Index

现在 *.cshtml 文件与其 @model 具有相同的命名空间,因此可以访问它。

在上面的示例中,要访问 @model,我们可以使用 @using 指令而不是 @namespace 指令。

@namespace 如何在 _ViewImports.cshtml 文件中工作?

每个文件有 @namespace@using 会在我们重新组织目录结构时造成维护问题。当我们把 index.cshtml 放入 Foo 目录时,它的 @namespace 并没有自动改变——我们需要记住手动改变它。如果我们使用代码分析工具来使我们的 *.cs 命名空间与其目录保持一致,这可能会成为一个问题。

这是 _ViewImports 中的 @namespace 变得方便的地方。它使 *.cshtml 文件命名空间自动与其目录对齐。

// Pages/_ViewImports
@namespace MyCustomNamespace

// Pages/Index.cshtml
@page
<p>@this.GetType().Namespace</p> // MyCustomNamespace
<p>@this.GetType().Name</p> // Pages_Index

// Pages/Foo/Index.cshtml
@page
<p>@this.GetType().Namespace</p> // MyCustomNamespace.Foo <- adapts to the directory
<p>@this.GetType().Name</p> // Pages_Foo_Index

不仅每个文件都有一个命名空间,而且每个命名空间适应其文件的目录

另见

我们可以在这里阅读 @namespace 存在的基本原理:https://github.com/aspnet/Razor/issues/1159