ASP.NET 视图组件:删除默认视图路径

Mat*_*sen 3 razor asp.net-core-mvc asp.net-core-viewcomponent

我想返回一个具有特定视图路径的视图,如下所示return View(~/Views/Home)。要返回的类型是IViewComponentResult.

但是,当站点被渲染时,它会尝试查找以下视图:Components/{controller-name}/~/Views/Home

所以我想问你们是否知道Components/{controller-name}/从路径中删除的聪明方法。我的视图组件类是从该类派生的ViewComponent

与此相关的问题是,现在您必须有一个“Components”文件夹,其中包含控制器名称作为子文件夹,其中包含 Default.cshtml 文件。我不喜欢将所有组件都放在一个文件夹中。我希望你有一个解决方案。

Ala*_*sai 5

约定发生在ViewViewComponentResult因此如果你不想要约定,你将不得不实现你自己的约定IViewComponentResult

由于 mvc 是开源的,您可以复制所有内容ViewViewComponentResult,然后更改约定位。

所以基本上必须做两件事:

  1. 创建你自己的IViewComponentResult- 让我们称之为MyViewViewComponentResult
  2. 在您的实现中创建一个助手ViewComponent来替换原始的- 目的是返回您在步骤 1 中创建的View()自定义MyViewViewComponentResult

创建你自己的IViewComponentResult

该约定发生在 ExecuteAsync 处:

public class ViewViewComponentResult : IViewComponentResult
{
    // {0} is the component name, {1} is the view name.
    private const string ViewPathFormat = "Components/{0}/{1}";
    private const string DefaultViewName = "Default";

    ....

    public async Task ExecuteAsync(ViewComponentContext context)
    {
        ....
        if (result == null || !result.Success)
        {
            // This will produce a string like:
            //
            //  Components/Cart/Default
            //
            // The view engine will combine this with other path info to search paths like:
            //
            //  Views/Shared/Components/Cart/Default.cshtml
            //  Views/Home/Components/Cart/Default.cshtml
            //  Areas/Blog/Views/Shared/Components/Cart/Default.cshtml
            //
            // This supports a controller or area providing an override for component views.
            var viewName = isNullOrEmptyViewName ? DefaultViewName : ViewName;
            var qualifiedViewName = string.Format(
                CultureInfo.InvariantCulture,
                ViewPathFormat,
                context.ViewComponentDescriptor.ShortName,
                viewName);

            result = viewEngine.FindView(viewContext, qualifiedViewName, isMainPage: false);
        }

        ....
    }

    .....
}
Run Code Online (Sandbox Code Playgroud)

所以将其更改为您的需要

在你的实现中创建一个助手ViewComponent来替换原来的View

所以在原来的基础上

/// <summary>
/// Returns a result which will render the partial view with name <paramref name="viewName"/>.
/// </summary>
/// <param name="viewName">The name of the partial view to render.</param>
/// <param name="model">The model object for the view.</param>
/// <returns>A <see cref="ViewViewComponentResult"/>.</returns>
public ViewViewComponentResult View<TModel>(string viewName, TModel model)
{
    var viewData = new ViewDataDictionary<TModel>(ViewData, model);
    return new ViewViewComponentResult
    {
        ViewEngine = ViewEngine,
        ViewName = viewName,
        ViewData = viewData
    };
}
Run Code Online (Sandbox Code Playgroud)

你会做类似的事情

/// <summary>
/// Returns a result which will render the partial view with name <paramref name="viewName"/>.
/// </summary>
/// <param name="viewName">The name of the partial view to render.</param>
/// <param name="model">The model object for the view.</param>
/// <returns>A <see cref="ViewViewComponentResult"/>.</returns>
public MyViewViewComponentResult MyView<TModel>(string viewName, TModel model)
{
    var viewData = new ViewDataDictionary<TModel>(ViewData, model);
    return new MyViewViewComponentResult
    {
        ViewEngine = ViewEngine,
        ViewName = viewName,
        ViewData = viewData
    };
}
Run Code Online (Sandbox Code Playgroud)

所以将来你会打电话MyView()而不是View()

更多信息请查看另一个SO:更改 Asp.Net 5 中的组件视图位置