Это интересный вопрос! Ваш общий подход к отображению действия для каждой страницы и возврату PartialViewResult
для внутреннего содержимого этой страницы имеет для меня смысл.
Однако, если единственное различие между полным представлением и частичным представлением заключается в общих элементах, я бы искал способы централизации представлений точки входа, если не самих действий точки входа, поскольку в противном случае они будут действительно повторяющийся.
Ниже я приведу базовую стратегию, которую я бы рассмотрел для работы с основной точкой входа.
Примечание. Учитывая природу вопроса, я предполагаю, что вам удобно реализовывать часть AJAX, и вместо этого сосредоточусь исключительно на серверной архитектуре, которая Я считаю, что в основе вашего вопроса. Очевидно, что существующие ответы касаются реализации на стороне клиента, если это важно.
Посмотреть модели
Для начала вы можете установить общую модель представления, которая обрабатывает весь контент страницы. Это может включать свойства, например. элементы навигации. Но он также будет содержать имя (частичного) представления, а также модель представления для этого представления, так как они вам, вероятно, понадобятся для предварительного рендеринга внутреннего содержимого:
public class PageViewModel
{
…
public string View { get; set; }
public object ViewModel { get; set; }
}
Затем у вас будут отдельные модели просмотра для каждой страницы, например:
public class BarListViewModel
{
public Collection<Bar> Bars { get; } = new();
}
Контроллер
Теперь в вашем контроллере вы введете метод, который устанавливает BarListViewModel
, так что вам не нужно повторять свою логику между вашей точкой входа, а также действиями, которые возвращают частичное представление:
[NonAction]
public BarListViewModel GetBarListViewModel()
{
var viewModel = new BarListViewModel()
{
Bars = …
};
return viewModel;
}
Теперь у вас может быть действие, которое доставляет вашу страницу Bars
, подобное тому, что вы предложили:
public IActionResult Bars() => PartialView(GetBarListViewModel());
Но вместо того, чтобы иметь разные действия Index
для каждого фрагмента, вы могли бы вместо этого иметь что-то вроде следующего
public IActionResult Index(Page page = "Home")
{
var viewModel = new PageViewModel
{
View = page.ToString(),
ViewModel = page switch
{
"Bars" => GetBarListViewModel(),
_ => GetDefaultViewModel()
}
};
return View("Index", viewModel);
}
Это обеспечивает единую «диспетчеризацию» для подключения любой точки входа без необходимости создавать новое действие или представление для каждой из них.
Вид
Наконец, в вашем Index.cshtml
у вас будет что-то вроде следующего для динамического внедрения правильного частичного представления на основе модели представления:
@model PageViewModel
…
<main>
@await Html.PartialAsync(Model.View, Model.ViewModel)
</main>
…
Это загрузит, например. Bars.cshtml
, который будет содержать логику для цикла по свойству BarListViewModel.Bars
.
Примечание. Предполагается, что вы хотите предварительно отрендерить свое частичное представление на стороне сервера. Очевидно, что если вы хотите, чтобы начальная загрузка происходила через AJAX, вам не нужно передавать вложенный BarListViewModel
или вызывать PartialAsync()
.
Маршрутизация
Предположительно, вышеприведенное будет сочетаться с конфигурацией маршрута, которая позволит передавать page
в качестве параметра маршрута — возможно, даже запекая значения по умолчанию Controller
и Action
для вашей точки входа:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{page?}",
new { controller = "Home", action = "Index" }
);
});
Примечание. Очевидно, что вам нужно быть осторожным, чтобы не заблокировать вызовы AJAX или другие точки входа с чрезмерно жадным маршрутом. Вышеупомянутое предназначено только как базовая демонстрация того, как захватить параметр маршрута page
.
Вывод
Это похоже на подход, предложенный @User1997, но позволяет повторно использовать их предложенное Index.cshtml
и подразумеваемое Index()
действие для < em>все ваши точки входа. И, конечно же, если бы у вас было несколько контроллеров, которые следовали этому шаблону, его можно было бы даже обобщить как базовый контроллер.
person
Jeremy Caney
schedule
05.02.2021