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?
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