Change component view location in Asp.Net 5

余生颓废 提交于 2019-12-06 07:08:02

问题


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

Is there a way to change this to:

Views/NameOfControllerUsingComponent/Components/ComponentName.cshtml
Views/Shared/Components/ComponentName.cshtml

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?


回答1:


That convention is only applied if you create a view component that derives from the base ViewComponent provided by the framework.

That class defines the View helpers, which return a 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
    };
}

The ViewViewComponentResult is where the conventions are defined:

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);
    }

    ...

}

Notice that if you return from your view component the full path to a view as the view name, then the view component will use the specified view. Something like:

return View("~/Views/Shared/Components/ComponentName.cshtml")

Since there is no way to modify the conventions in ViewViewComponentResult and your approach would only work for view components with a single view, you could build something using the root view paths approach:

  • Create your own ViewComponent class extending the existing one.
  • Add new helper methods or hide the existing View methods to return a view using a full path:

    public ViewViewComponentResult MyView<TModel>(TModel model)
    {
        var viewName = string.Format(
                "~/Views/Shared/Components/{0}.cshtml", 
                this.ViewComponentContext.ViewComponentDescriptor.ShortName)
        return View(viewName, model);
    }
    
  • If you add new methods you might be able to add them as extension methods of ViewComponent instead of having to create your own class.

Another alternative would be creating a class SingleViewViewComponent copying the code for ViewComponent but replacing the implementation of ViewViewComponentResult View<TModel>(string viewName, TModel model). Then when creating your view components, you would inherit from SingleViewViewComponent instead of ViewComponent.



来源:https://stackoverflow.com/questions/33527801/change-component-view-location-in-asp-net-5

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!