ASP.NET视图组件:删除要查看的默认路径

时间:2017-07-10 20:09:50

标签: 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文件的子文件夹。我不喜欢将所有组件放在一个文件夹中。我希望你有一个解决方案。

1 个答案:

答案 0 :(得分:3)

约定发生在ViewViewComponentResult,因此如果您不想要约定,则必须实现自己的IViewComponentResult

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

所以基本上要做两件事:

  1. 创建自己的IViewComponentResult - 让我们称之为MyViewViewComponentResult
  2. 在已实施的ViewComponent中创建帮助以替换原始View() - 目的是返回您在步骤1中创建的自定义MyViewViewComponentResult
  3. 创建自己的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);
            }
    
            ....
        }
    
        .....
    }
    

    所以根据需要改变它

    在已实施的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
        };
    }
    

    你会做类似

    的事情
    /// <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
        };
    }
    

    以后您可以拨打MyView()而不是View()

    更多信息请查看另一个SO:Change component view location in Asp.Net 5