Форма отправки ASP.NET Core MVC в частичном представлении / ViewComponent

У меня есть меню и область содержимого, в которой отображается содержимое на основе выбранного элемента в меню. Поскольку пользователю разрешено изменять структуру главного меню, я решил, что все будет на странице / home / index и будет иметь идентификатор, назначенный для контента, который необходимо показать. Я начал с идеи ввести частичные представления, но понял, что ASP.NET Core больше не имеет RenderAction и был заменен ViewComponents. Итак, я использовал ViewComponents, и все работает нормально, за исключением того, что я наткнулся на ситуацию, когда мне нужен компонент в качестве формы отправки.

В качестве примера: Один пункт меню - это меню - компонент, который показывает список пользователей. Другой пункт меню - это компонент, который создает нового пользователя. При создании пользовательского компонента у меня будет форма, которую необходимо заполнить, и при успешной отправке я хочу перенаправить пользователя на компонент, который показывает список пользователей. В случае неудачной отправки, ошибки или неправильного ввода я, конечно, не хотел бы перенаправлять пользователя в список пользователей.

Поскольку задача ViewComponents - отображать представление, как мне подойти к этой проблеме? Ищу указатели в правильном направлении. У меня мало опыта в этой области, поэтому я буду благодарен за любую помощь.

ОБНОВЛЕНИЕ

В Index.cshtml:

<tbody>
    @foreach (string item in Model.Components)
    {
        <tr>
            <td>
                <div class="col-md-3">
                    @await Component.InvokeAsync(@item)
                </div>
            </td>
        </tr>
    }
</tbody>

Это внутри области содержимого. Компоненты - это строковые имена компонентов, которые я хотел бы отображать в области содержимого (в настоящее время перечисляются один за другим).

My ViewComponent, который вызывается, когда я нажимаю на пункт меню для отображения формы:

public class TestFormViewComponent : ViewComponent
{
    public async Task<IViewComponentResult> InvokeAsync()
    {
        return View("_TestForm", new TestModelPost());
    }
}

Мой компонент _TestForm.cshtml:

@model TestModelPost
<form asp-controller="Home" asp-action="TestPost" method="post">
    <label asp-for="Name"></label>
    <input asp-for="Name" /><br />
    <label asp-for="Surname"></label>
    <input asp-for="Surname" /><br />
    <button type="submit">Go</button>
</form>

И действие TestPost вызвало:

[HttpPost]
public IActionResult TestPost(TestModelPost model)
{
    // Save model data, etc
    // !ModelState.IsValid -> go back to form

    // Success -> go to specific id
    return RedirectToAction("Index", new { id = 1 });
}

Как мне подойти к этому? Вернее, я вообще на правильном пути? Я не уверен, как я мог бы вернуться к тому представлению, которое я создал в своем компоненте _TestForm, если введенные данные были неправильными.




Ответы (2)


Компоненты просмотра, как и дочерние действия перед ними в ASP.NET MVC, не поддерживают POST. Вам нужно полноценное действие для обработки сообщения формы, которое должно будет возвращать полное представление. По сути, вам просто нужно думать об этом более абстрактно.

Компонент представления - это, в конечном счете, просто средство сброса некоторого HTML-кода в конечный ответ. Когда полный ответ возвращается клиенту, нет понятия о том, что было компонентом представления, частичным представлением и т. Д. Это просто HTML-документ. Часть этого HTML-документа - ваша форма. Эта форма будет иметь действие, которое в конечном итоге должно быть маршрутом, обрабатываемым одним из действий вашего контроллера. Традиционная форма публикации вызывает изменение всего представления браузера, поэтому ответ от этого действия должен быть либо полным представлением, либо перенаправлением на действие, которое возвращает полное представление. Перенаправление является более подходящим путем, следуя шаблону PRG. Затем именно это представление, которое в конечном итоге возвращается, определяет, как создается контент, используя компоненты представления, частичные данные и т. Д. В зависимости от ситуации.

Короче говоря, это действительно не имеет никакого отношения к вашему компоненту представления. Все, что он делает, это просто отбрасывает код формы на страницу.

Для таких форм, которые являются частью макета, обычно лучше включать скрытый ввод, который содержит «URL-адрес возврата» в форме. Действие, обрабатывающее форму, затем может перенаправить обратно на этот URL-адрес после выполнения того, что ему нужно сделать, чтобы создать впечатление, что пользователь остался на том же месте.

person Chris Pratt    schedule 12.10.2018

Пожалуйста, перейдите по следующей ссылке:

https://andrewlock.net/an-introduction-to-viewcomponents-a-login-status-view-component/

это может помочь

public class LoginStatusViewComponent : ViewComponent
{
    private readonly SignInManager<ApplicationUser> _signInManager;
    private readonly UserManager<ApplicationUser> _userManager;

    public LoginStatusViewComponent(SignInManager<ApplicationUser> signInManager, UserManager<ApplicationUser> userManager)
    {
        _signInManager = signInManager;
        _userManager = userManager;
    }

    public async Task<IViewComponentResult> InvokeAsync()
    {
        if (_signInManager.IsSignedIn(HttpContext.User))
        {
            var user = await _userManager.GetUserAsync(HttpContext.User);
            return View("LoggedIn", user);
        }
        else
        {
            return View();
        }
    }
}

Наш метод InvokeAsync довольно понятен. Мы проверяем, вошел ли текущий пользователь в систему с помощью SignInManager ‹>, и, если это так, мы извлекаем связанный ApplicationUser из UserManager‹>. Наконец, мы вызываем вспомогательный метод View, передавая шаблон для рендеринга и пользователя модели. Если пользователь не вошел в систему, мы вызываем вспомогательный View без аргумента шаблона.

В соответствии с вашим сегментом кода вы можете попробовать изменить его следующим образом:

public class TestFormViewComponent : ViewComponent
{
    public async Task<IViewComponentResult> InvokeAsync()
    {
      if (_signInManager.IsSignedIn(HttpContext.User))
        {
       //user list display
        return View("_TestForm", new TestModelPost());
        }
      else
        {
          return View();
        }
    }
}
person Debabrata    schedule 12.10.2018
comment
Здравствуйте, я обновил свой первый пост написанным мной кодом. Есть еще указатели? - person Dely; 12.10.2018