Reusable Patterns for ASP.NET Core MVC Views

Answered using OpenAI o1 mini by OpenAI o1

Question:

в проекте asp.net core mvc есть код

  [HttpGet]
  public IActionResult Upload()
  {
    var selectProjectViewModel = HttpContext.Session.GetObjectFromJson<SelectProjectViewModel>("SelectProject");
    return View(selectProjectViewModel);
  }

какой паттерн можно использовать, что бы вызывать его в разных представлениях?

Answer:

В ASP.NET Core MVC для повторного использования кода, который обрабатывает логику загрузки данных или состояния, можно использовать несколько паттернов. Вот несколько подходов, которые могут помочь вам вызывать этот код в разных представлениях:

1. Паттерн "View Component"

View Component позволяет инкапсулировать логику и представление, которые могут быть повторно использованы в разных местах приложения. Вы можете создать View Component, который будет обрабатывать загрузку данных и возвращать представление.

Пример:

public class SelectProjectViewComponent : ViewComponent
{
    public IViewComponentResult Invoke()
    {
        var selectProjectViewModel = HttpContext.Session.GetObjectFromJson<SelectProjectViewModel>("SelectProject");
        return View(selectProjectViewModel);
    }
}

Затем вы можете использовать этот компонент в любом представлении:

@await Component.InvokeAsync("SelectProject")

2. Паттерн "Partial View"

Если вам нужно просто отобразить часть представления, вы можете создать частичное представление и вызывать его из разных представлений. Логика загрузки данных может быть вынесена в контроллер.

Пример:

[HttpGet]
public IActionResult Upload()
{
    var selectProjectViewModel = HttpContext.Session.GetObjectFromJson<SelectProjectViewModel>("SelectProject");
    return PartialView("_SelectProjectPartial", selectProjectViewModel);
}

И затем вы можете использовать это частичное представление в других представлениях:

@Html.Partial("_SelectProjectPartial", Model)

3. Сервисный слой

Если логика загрузки данных более сложная или требует взаимодействия с базой данных, вы можете создать сервисный класс, который будет отвечать за получение данных. Это позволит вам инкапсулировать логику и использовать её в разных контроллерах.

Пример сервиса:

public class ProjectService
{
    private readonly IHttpContextAccessor _httpContextAccessor;

    public ProjectService(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    public SelectProjectViewModel GetSelectProjectViewModel()
    {
        return _httpContextAccessor.HttpContext.Session.GetObjectFromJson<SelectProjectViewModel>("SelectProject");
    }
}

И затем использовать этот сервис в контроллерах:

public class YourController : Controller
{
    private readonly ProjectService _projectService;

    public YourController(ProjectService projectService)
    {
        _projectService = projectService;
    }

    [HttpGet]
    public IActionResult Upload()
    {
        var selectProjectViewModel = _projectService.GetSelectProjectViewModel();
        return View(selectProjectViewModel);
    }
}

4. Фильтры

Если вы хотите, чтобы логика выполнялась автоматически перед выполнением действия контроллера, вы можете создать фильтр, который будет загружать данные в ActionExecutingContext.

Пример:

public class LoadSelectProjectAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        var selectProjectViewModel = context.HttpContext.Session.GetObjectFromJson<SelectProjectViewModel>("SelectProject");
        context.ActionArguments["selectProjectViewModel"] = selectProjectViewModel;
    }
}

И затем применить его к контроллеру или методу:

[LoadSelectProject]
public IActionResult Upload(SelectProjectViewModel selectProjectViewModel)
{
    return View(selectProjectViewModel);
}

Заключение

Выбор подходящего паттерна зависит от ваших конкретных требований и архитектуры приложения. Если вам нужно просто повторно использовать представление, View Component или Partial View могут быть хорошими вариантами. Если логика более сложная, стоит рассмотреть использование сервисного слоя или фильтров.