I want to return a View with a specific path to the view like so, return View(~/Views/Home)
. The type to be returned is an IViewComponentResult
.
However, when the site gets rendered, it tries to find the view under: Components/{controller-name}/~/Views/Home
.
So I want to ask you guys, if you know a smart way to delete Components/{controller-name}/
from the path. My view component class is deriving from the ViewComponent
class.
The problem regarding this is that right now, you have to have a "Components" folder with the name of the controller as a subfolder which contains a Default.cshtml file. I do not like to have all my components inside one folder. I hope you have a solution.
The convention happened in ViewViewComponentResult
hence if you don't want the convention, you will have to implement your own IViewComponentResult
since mvc is open source, you could copy all the ViewViewComponentResult
and then change the convention bit.
so essentially two things has to be done:
IViewComponentResult
- lets call it MyViewViewComponentResult
ViewComponent
to replace the original View()
- purpose is to returns the custom MyViewViewComponentResult
you created at step 1IViewComponentResult
the convention happened at 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);
}
....
}
.....
}
so change it to your need
ViewComponent
which replace the original View
so base on original
/// <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
};
}
you would do something like
/// <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
};
}
so in future you would call MyView()
instead of View()
more info check out another SO: Change component view location in Asp.Net 5