当视图位于其他程序集中时如何寻址视图? .NET Core Web 应用程序

问题描述 投票:0回答:1

我有一个具有不同程序集(模块)的 ASP.NET Core MVC Web 应用程序。每个模块都定义有相应的 URL。

我创建了一个新的路由前缀,将模块名称添加到 URL 中。该前缀称为

module

另一方面,我有 2 个模块,称为

AccessControl
TimeAttendance
。它们都有以下控制器(注意它们具有相同的名称)

namespace Modules.AccessControl.UI.Controllers
{
    [Route("[module]/[controller]")]
    public class AreaController : Controller
    {
        [HttpGet]
        public IActionResult Index()
        {
            return View();
        }
    }
}

namespace Modules.TimeAttendance.UI.Controllers
{
    [Route("[module]/[controller]")]
    public class AreaController : Controller
    {
        [HttpGet]
        public IActionResult Index()
        {
            return View();
        }
    }
}

两者都有相应的视图,称为

Index

enter image description here

enter image description here

嗯....当我在浏览器中加载此内容时:

https://localhost:44375/TimeAttendance/Area
,执行了正确的
Index
操作(来自
Modules.TimeAttendance.UI
程序集),但是,正在尝试查看来自
Modules.AccessControl.UI
的视图。

关于这个我知道两件事:

  1. 我可以通过使用调用中的完整路径来指向正确的视图
    return View()
  2. 由于
    AccessControl
    模块是第一个要加载的程序集(模块),我认为这就是显示该程序集视图的原因。

默认调用

return View()
时,有没有办法使用完整的程序集来寻址视图?

我之前在 Swagger 中也遇到过同样的问题,但是,我可以设置使用完整的程序集名称。我希望在解决正确的观点时我也能这样做。

编辑:

我创建了一个自定义

IViewLocationExpander
来修改视图搜索路径。现在显示此错误:

enter image description here

如何使用完整路径来寻址视图?我也尝试过

/Modules.TimeAttendance.UI/Views/Area/Index.cshtml
,但也没有用。

编辑2:路由

public class Module(string routePrefix, IModuleStartup startup)
{
    /// <summary>
    /// Gets the route prefix to all controller and endpoints in the module.
    /// </summary>
    public string RoutePrefix { get; } = routePrefix;

    /// <summary>
    /// Gets the startup class of the module.
    /// </summary>
    public IModuleStartup Startup { get; } = startup;

    /// <summary>
    /// Gets the assembly of the module.
    /// </summary>
    public Assembly Assembly => Startup.GetType().Assembly;
}

public class ModuleRoutingConvention(IEnumerable<Module> modules) : IActionModelConvention
{
    private readonly IEnumerable<Module> _modules = modules;

    public void Apply(ActionModel action)
    {
        var module = _modules.FirstOrDefault(m => action.Controller.ControllerType.Assembly.FullName?.StartsWith($"Modules.{m.RoutePrefix}") ?? false);
        if (module == null)
        {
            return;
        }

        action.RouteValues.Add("module", module.RoutePrefix);
    }
}

public class ModuleRoutingMvcOptionsPostConfigure : IPostConfigureOptions<MvcOptions>
{
    private readonly IEnumerable<Module> _modules;

    public ModuleRoutingMvcOptionsPostConfigure(IEnumerable<Module> modules)
    {
        _modules = modules;
    }

    public void PostConfigure(string? name, MvcOptions options)
    {
        options.Conventions.Add(new ModuleRoutingConvention(_modules));
    }
}

/// <summary>
/// Adds a module.
/// </summary>
/// <param name="services"></param>
/// <param name="routePrefix">The prefix of the routes to the module.</param>
/// <typeparam name="TStartup">The type of the startup class of the module.</typeparam>
/// <returns></returns>
public static class ModuleServiceCollection
{
    /// <summary>
    /// Adds a module.
    /// </summary>
    /// <param name="services"></param>
    /// <param name="routePrefix">The prefix of the routes to the module.</param>
    /// <typeparam name="TStartup">The type of the startup class of the module.</typeparam>
    /// <returns></returns>
    public static IServiceCollection AddModule<TStartup>(this IServiceCollection services, string routePrefix, IConfiguration configuration)
        where TStartup : IModuleStartup, new()
    {
        // Register assembly in MVC so it can find controllers of the module
        services.AddControllers().ConfigureApplicationPartManager(manager =>
            manager.ApplicationParts.Add(new AssemblyPart(typeof(TStartup).Assembly)));

        var startup = new TStartup();
        startup.ConfigureServices(services, configuration);

        services.AddSingleton(new Module(routePrefix, startup));

        return services;
    }
}
model-view-controller asp.net-core-mvc
1个回答
0
投票

enter image description here

错误表明您的控制器将被击中,但无法在

/Modules.TimeAttendace.UI.Views/Area
文件夹中找到视图

尝试将您的

views
文件夹修改为
Modules.TimeAttendace.UI.Views
或向我们展示您如何修改 View Engine 的默认位置

© www.soinside.com 2019 - 2024. All rights reserved.