Как обрабатывать форму сообщения из View Component (Razor Core 2)

В эти выходные много борьбы с View Component.

Я пытаюсь добавить выпадающий список, который выполняет автоматическую замену обратной передачи. Этот выпадающий список находится на компоненте представления.

У меня 2 проблемы:

  1. Я не получаю asp-page-handler после поста, работает ли он так, как я его реализовал в теге form?
  2. Опубликовать вызов метода public void OnPost на странице бритвы, содержащей компонент вида. Я думаю, что было бы лучше иметь метод на компонент View, как OnChangeProject?

Код моего просмотра (View Component):

<form asp-page-handler="ChangeProject" method="post">

    @Html.AntiForgeryToken()
    @Html.DropDownList("id", new SelectList(Model, "Id", "Id"), new { onchange = "this.form.submit()" })

</form>

Заранее спасибо!!

4 ответа

Я испытал ту же проблему, и способ, которым я исправил это, уже ответил на Ваш вопрос.

Вызов формы выполняется на странице, где вы встроили свой View View. Я не думаю, что было бы даже возможно вызвать обработчик в вашем компоненте просмотра с asp-page-handler так как это хелпер тегов Razor Pages.

То, как я это получил, - это просто положить метод обработчика страниц на PageModel это вложение компонента View. В вашем случае вы можете просто реализовать этот обработчик на своей странице Razor:

public IActionResult OnPostChangeProject()
{
    // ... do Something
}

Я не знаю, хотя, как это будет работать, чтобы вызвать метод контроллера в вашем компоненте просмотра. Возможно, создайте новый класс Controller и направьте его asp-controller а также asp-action в вашей форме тега.

Вы должны помнить, что обработчики Page можно рассматривать как удобные методы. Все, что делает платформа ASP.Net Core, — это просмотр параметров строки запроса и данных формы и преобразование их в вызовы обработчика страниц. И даже несмотря на то, что обработчики недоступны в компонентах представления или частичных представлениях, вы все равно можете получить доступ ко всем необходимым ингредиентам, внедривIHttpContextAccessorв Представление. Он предоставит вамHttpContext.Requestкоторый содержит какQueryиFormхарактеристики.

Затем вы можете создать свой собственный преобразователь Handler. Вот один, например:

          public class HandlerMapping
    {
        public string Name { get; set; }
        public System.Delegate RunDelegate { get; set; }

        public HandlerMapping(string name, Delegate runDelegate)
        {
            RunDelegate = runDelegate;
            Name = name;
        }
    }


    public class PartialHandlerMapper
    {
        IHttpContextAccessor _contextAccessor;

        public PartialHandlerMapper(IHttpContextAccessor contextAccessor)
        {
            _contextAccessor = contextAccessor;
        }


        public void RouteHandler(List<HandlerMapping> handlerMappings, string PartialDescriminatorString = null)
        {
            var handlerName = _contextAccessor.HttpContext.Request.Query["handler"];
            var handlerMapping = handlerMappings.FirstOrDefault(x => x.Name == handlerName);

            if (handlerMapping != null)
            {
                IFormCollection form;
                try
                {
                    form = _contextAccessor.HttpContext.Request.Form;
                }
                catch 
                {
                    return;
                }

                if (!string.IsNullOrWhiteSpace(PartialDescriminatorString) && form[nameof(PartialDescriminatorString)] != PartialDescriminatorString)
                    return;

                List<Object> handlerArgs = new List<object>();

                var prmtrs = handlerMapping.RunDelegate.Method.GetParameters();

                foreach (var p in prmtrs)
                {
                    object nv = null;

                    var formValue = form[p.Name];

                    if (!StringValues.IsNullOrEmpty(formValue))
                    {
                        try
                        {
                            nv = TypeDescriptor.GetConverter(p.ParameterType).ConvertFromString(formValue);
                        }
                        catch (FormatException)
                        {
                            //throw new FormatException($"Could not cast form value '{formValue}' to parameter {p.Name} (type {p.ParameterType}) of handler {handlerName}. Make sure you use correct type parameter. ");
                            nv = Activator.CreateInstance(p.ParameterType);
                        }
                        catch (ArgumentException)
                        {
                            nv = Activator.CreateInstance(p.ParameterType);
                        }
                    }
                    else
                        nv = Activator.CreateInstance(p.ParameterType);

                    handlerArgs.Add(nv);
                }

                handlerMapping.RunDelegate.DynamicInvoke(handlerArgs.ToArray());
            }

        }
    } 

И внедрить его в сервисный контейнер:

      services.AddScoped<PartialHandlerMapper>();

А вот пример раздела кода частичного просмотра корзины:

      @inject ShoppingManager shoppingManager
@inject PartialHandlerMapper partialHandlerMappping

@{
    string ToggleCartItemTrialUseHandler = nameof(ToggleCartItemTrialUseHandler);
    string DeleteCartItemHandler = nameof(DeleteCartItemHandler);

    List<HandlerMapping> handlerMappings = new List<HandlerMapping> {
            new HandlerMapping (ToggleCartItemTrialUseHandler, (Guid? PicID, bool? CurrentValue) => {
                if (PicID == null || CurrentValue == null)
                    return;

                shoppingManager.UpdateTrial((Guid)PicID, !(bool)CurrentValue);
            }),
            new HandlerMapping (DeleteCartItemHandler, (Guid? PicID) => {
                if (PicID == null)
                    return;

                shoppingManager.RemoveProductFromCart((Guid)PicID);
            })
    };

    partialHandlerMappping.RouteHandler(handlerMappings);

    var cart = shoppingManager.GetSessionCart();
    
}

Пример элемента формы из того же представления:

      <td align="center" valign="middle">
   <form asp-page-handler="@DeleteCartItemHandler">
      <input name=PicID type="hidden" value="@i.PicID" />
      <button>
         Delete
      </button>
   </form>
</td>

Где @i — товар в корзине

Есть похожий вопрос о частичных взглядах. Почему обработчик частичного просмотра не запускается при обратной передаче. Не удается найти подходящее объяснение или статью, которая четко объясняет это. Форма частичного просмотра

Можно создать комбо (Контроллер /ViewComponent), украсив контроллер ViewComponent(Name="myviewcomponent").

Затем создайте invokeasync как обычно, но поскольку контроллер не наследуется от ViewComponent, возвращаемый результат будет одним из результатов ViewComponent (ViewViewComponentResult, et).

Форма в компоненте представления может иметь кнопку с помощниками тегов asp-controller/action, нацеленными на контроллер / действие.

Другие вопросы по тегам