Change component view location in Asp.Net 5

Mig*_*ura 3 asp.net-core-mvc asp.net-core

On ASP.NET 5 a Component view must be in one of two places:

Views/NameOfControllerUsingComponent/Components/ComponentName/Default.cshtml
Views/Shared/Components/ComponentName/Default.cshtml
Run Code Online (Sandbox Code Playgroud)

Is there a way to change this to:

Views/NameOfControllerUsingComponent/Components/ComponentName.cshtml
Views/Shared/Components/ComponentName.cshtml
Run Code Online (Sandbox Code Playgroud)

So basically, remove the folder ComponentName and change the view name from Default.cshtml to ComponentName.cshtml.

For me it makes more sense ... Is it possible?

Dan*_*.G. 6

该约定仅适用于创建从ViewComponent框架提供的基础派生的视图组件。

该类定义了View帮助程序,它返回一个ViewViewComponentResult

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)

ViewViewComponentResult是定义约定的地方:

private const string ViewPathFormat = "Components/{0}/{1}";
private const string DefaultViewName = "Default";

public async Task ExecuteAsync(ViewComponentContext context)
{
    ...

    string qualifiedViewName;
    if (!isNullOrEmptyViewName &&
        (ViewName[0] == '~' || ViewName[0] == '/'))
    {
        // View name that was passed in is already a rooted path, the view engine will handle this.
        qualifiedViewName = ViewName;
    }
    else
    {
        // 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;

        qualifiedViewName = string.Format(
            CultureInfo.InvariantCulture,
            ViewPathFormat,
            context.ViewComponentDescriptor.ShortName,
            viewName);
    }

    ...

}
Run Code Online (Sandbox Code Playgroud)

请注意,如果您从视图组件返回视图的完整路径作为视图名称,则视图组件将使用指定的视图。就像是:

return View("~/Views/Shared/Components/ComponentName.cshtml")
Run Code Online (Sandbox Code Playgroud)

由于无法修改中的约定,ViewViewComponentResult并且您的方法仅适用于具有单个视图的视图组件,因此您可以使用根视图路径方法构建一些内容:

  • 创建您自己的ViewComponent类,扩展现有的类。
  • 添加新的辅助方法或隐藏现有View方法以使用完整路径返回视图:

    public ViewViewComponentResult MyView<TModel>(TModel model)
    {
        var viewName = string.Format(
                "~/Views/Shared/Components/{0}.cshtml", 
                this.ViewComponentContext.ViewComponentDescriptor.ShortName)
        return View(viewName, model);
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 如果您添加新方法,您可以将它们添加为扩展方法,ViewComponent而不必创建自己的类。

另一种选择是创建一个类来SingleViewViewComponent复制代码ViewComponent但替换ViewViewComponentResult View<TModel>(string viewName, TModel model). 然后在创建视图组件时,您将继承 fromSingleViewViewComponent而不是ViewComponent.