Катится мой собственный @Html.BeginfBrm()

Я пишу пользовательский набор проверки, который будет отображать все недостающие элементы в div. Я хотел бы иметь возможность использовать пользовательские @Html.BeginForm() метод, который запишет этот div, но я действительно не уверен, с чего начать, так как этот орех немного сложнее взломать, чем просто HTML-расширение, которое записывает тег или строку (форма инкапсулирует данные / элементы управления и закрывается } в конце).

Я посмотрел на версию метаданных встроенного BeginForm() метод, и это не сильно помогло мне. По сути, я просто хочу расширить этот метод, если это возможно, и сделать так, чтобы он выписал MvcHtmlString из div это будет показано / скрыто от JavaScript.

в конечном счете, я пытаюсь понять, как написать этот пользовательский помощник, в котором есть начальный и конечный компоненты.

@using(Html.BeginForm())
{
...

}

Я хотел бы иметь возможность сделать что-то вроде этого:

@using(Html.VBeginForm())
{
...

}

и это сделать мой дополнительный HTML

РЕДАКТИРОВАТЬ: добавить код из предложения ниже

public class VBeginForm : IDisposable
{
    private readonly HtmlHelper _helper;
    public VBeginForm(HtmlHelper htmlHelper, string areaName)
    {
        _helper = htmlHelper;
        var container = new TagBuilder("form");
        container.GenerateId(areaName);
        var writer = _helper.ViewContext.Writer;
        writer.Write(container.ToString(TagRenderMode.StartTag));
    }

    public void Dispose()
    {
        _helper.ViewContext.Writer.Write("</form>");
    }
}

2 ответа

Решение

Вам нужно написать метод расширения для HtmlHelper класс, который печатает в helper.ViewContext.Writer,

Метод должен вернуть IDisposable который печатает закрывающий тег в своем Dispose метод.

SLaks ответ правильный, но отсутствует какая-то дополнительная информация.

Если вы хотите использовать традиционную (не ненавязчивую) проверку на стороне клиента, вам нужно предоставить formContext и присвоить ему идентификатор, чтобы проверка на стороне клиента могла работать. В его объяснении эта часть отсутствует.

Самый простой способ добиться этого - использовать экземпляр экземпляра MvcForm класс, который создает formContextи реализует IDisposable интерфейс.

В этой реализации мне нужно было указать идентификатор формы:

public static MvcForm BeginFormDatosAdicionales(this HtmlHelper htmlHelper, 
   string id, ..., IDictionary<string, object> htmlAttributes = null)
{
  TagBuilder form = new TagBuilder("form");
  // attributes
  form.MergeAttributes(htmlAttributes);
  // action
  string formAction = ...;
  form.MergeAttribute("action", formAction);
  // method
  FormMethod method = ...;
  form.MergeAttribute("method", HtmlHelper.GetFormMethodString(method), true);
  // id
  form.MergeAttribute("id", id);

  // writes the form's opening tag in the ViewContext.Writer
  htmlHelper.ViewContext.Writer.Write(form.ToString(TagRenderMode.StartTag));

  // creates an MvcForm (disposable), which creates a FormContext, needed for
  // client-side validation. You need to supply and id for it
  MvcForm theForm = new MvcForm(htmlHelper.ViewContext);
  htmlHelper.ViewContext.FormContext.FormId = form.Attributes["id"];

  // The returned object implements IDisposable, and writes the closing form tag
  return theForm;
  }

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

bool idRequired = htmlHelper.ViewContext.ClientValidationEnabled
&& !htmlHelper.ViewContext.UnobtrusiveJavaScriptEnabled;

В этом случае вы должны быть осторожны, чтобы создавать разные идентификаторы для каждой формы на странице. Например, вы можете добавить целочисленный суффикс, который можно сохранить в HttpContext.Items и увеличивать при каждом создании нового идентификатора. Это гарантирует, что на одной странице все сгенерированные идентификаторы отличаются.

HttpContext.Current.Items["lastFormId"]
Другие вопросы по тегам