简体   繁体   English

ASP.NET Core 3.1 MVC 应用程序 - 在子目录中搜索视图

[英]ASP.NET Core 3.1 MVC app - search views in subdirectory

I know there is an area feature.我知道有一个区域特征。 But I think that is just to much for what I really need.但我认为这只是我真正需要的。

  • I have an netcoreapp3.1 build from the MVC template我有一个从 MVC 模板构建的netcoreapp3.1
  • I have a HomeController (namespace My.Project.Controllers )我有一个HomeController (命名空间My.Project.Controllers
  • I also have a SettingsController (namespace My.Project.Controllers.Admin )我还有一个SettingsController (命名空间My.Project.Controllers.Admin
  • In my _Layout.cshtml I link to the controller like this (generated link is https://localhost:5001/admin/settings/ as expected.在我的_Layout.cshtml中,我像这样链接到 controller(生成的链接是https://localhost:5001/admin/settings/符合预期。
@if (User.IsInRole("admin"))
{
    <li class="nav-item dropdown">
        <a class="nav-link dropdown-toggle text-dark" href="#" id="navbarDropdown" role="button"
            data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
            Admin
        </a>
        <div class="dropdown-menu" aria-labelledby="navbarDropdown">
            <a class="dropdown-item" asp-area="" asp-controller="settings" asp-action="Index">Settings</a>
        </div>
    </li>
}

I also added the first MapControllerRoute to my Startup.Configure method我还将第一个MapControllerRoute添加到我的Startup.Configure方法中

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(
            name: "admin",
            pattern: "admin/{controller=Home}/{action=Index}/{id?}"
            );
    endpoints.MapRazorPages();

    endpoints.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");
    endpoints.MapRazorPages();
});

The controller is invoked and调用 controller 并

public class SettingsController : Controller
{
    private readonly ISettingsProvider settingsProvider;

    public SettingsController(ISettingsProvider settingsProvider)
    {
        this.settingsProvider = settingsProvider;
    }

    public IActionResult Index()
    {
        var settings = settingsProvider.GetSettings();
        return View(settings);
    }
}

Now I get the following error现在我收到以下错误

An unhandled exception occurred while processing the request.处理请求时发生未处理的异常。 InvalidOperationException: The view 'Index' was not found. InvalidOperationException:未找到视图“索引”。 The following locations were searched:搜索了以下位置:
/Views/Settings/Index.cshtml /Views/Settings/Index.cshtml
/Views/Shared/Index.cshtml /Views/Shared/Index.cshtml
/Pages/Shared/Index.cshtml /Pages/Shared/Index.cshtml

As I already said, I also tried using Areas but that would require me to put my files inside an Areas folder with its own Views folder and viewstart etc.正如我已经说过的,我也尝试过使用 Areas,但这需要我将文件放在带有自己的Views文件夹和 viewstart 等的Areas文件夹中。

I worked a lot with nancy fx and I am used to the convention that views for My.Project.Modules.Admin.SettingsModule are searched inside Views/Admin/Settings first.我与 nancy fx 一起工作了很多,我习惯于首先在Views/Admin/Settings中搜索My.Project.Modules.Admin.SettingsModule视图的约定。

How do I achieve the same with ASP.NET Core MVC (for My.Project.Controllers.Admin.SettingsController search views in Views/Admin/Settings ?)如何使用 ASP.NET Core MVC 实现相同的功能(对于My.Project.Controllers.Admin.SettingsControllerViews/Admin/Settings中的搜索视图?)

- src/
  - Views/
    - Home/
      - Index.cshtml
    - Admin/
       - Settings/
         - Index.cshtml
  - Controllers/
    - Admin/
        SettingsController.cs
    - HomeController.cs

Have you tried this?你试过这个吗?

@using (Html.BeginForm("Index", "Settings", "Admin" FormMethod.Get))
{
   @if (User.IsInRole("admin"))
   {
<li class="nav-item dropdown">
    <a class="nav-link dropdown-toggle text-dark" href="#" id="navbarDropdown" role="button"
        data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
        Admin
    </a>
    <div class="dropdown-menu" aria-labelledby="navbarDropdown">
        <a class="dropdown-item" asp-area="" asp-controller="settings" asp-action="Index">Settings</a>
    </div>
</li>

} } } }

I believe your issue is in the creation of the routing.我相信您的问题在于创建路由。

There is more information about this here有更多关于此的信息here

For your current configuration I think, if you change your pattern it will solve your issue对于您当前的配置,我认为,如果您更改模式,它将解决您的问题

 pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}"

Solved解决了

There are four things that I had to do.我必须做四件事。

First, I had to setup a new Controller Route inside Startup.Configure首先,我必须在Startup.Configure中设置一个新的 Controller 路由

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
                name: "areas",
                pattern: "{area:exists}/{controller=Home}/{action=Index}");

        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Home}/{action=Index}/{id?}");

        endpoints.MapRazorPages();
    });

Second, I needed to tell my Controller that it belongs to the admin area.其次,我需要告诉我的 Controller 它属于管理区域。

[Area("admin")]
public class SettingsController : Controller
{
}

In my layout I had to set the asp-area property to admin在我的布局中,我必须将asp-area属性设置为admin

<a class="dropdown-item" asp-area="admin" asp-controller="settings" asp-action="Index">Settings</a>

but that was not enough since the default will only search in the following locations:但这还不够,因为默认只会在以下位置搜索:

InvalidOperationException: The view 'Index' was not found. The following locations were searched:

/Areas/admin/Views/Settings/Index.cshtml
/Areas/admin/Views/Shared/Index.cshtml
/Views/Shared/Index.cshtml
/Pages/Shared/Index.cshtml

So I had to add this to the ConfigureServices method.所以我不得不将它添加到ConfigureServices方法中。

services.Configure<RazorViewEngineOptions>(options =>
    {
        // {0} - Action Name
        // {1} - Controller Name
        // {2} - Area Name
        options.AreaViewLocationFormats.Add("/Views/{2}/{1}/{0}.cshtml");
    });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM