在 MVC 3.0 中重写 Html.BeginForm() 并保持不显眼的 javascript

发布于 2024-10-18 13:12:56 字数 2335 浏览 5 评论 0原文

这看起来有点愚蠢,但它仍然是我想学习的东西。

现在,在 ASP.NET MVC 3.0 中,您需要使用语法 @using (Html.BeginForm()) { ,然后使用 } 来关闭表单阻止获得新奇的“不引人注目的 javascript”,以免您想手动编写所有内容(这很好)。

由于某种原因(阅读:*OCD*)我不喜欢这样。我真的宁愿这样做......

@Html.BeginForm()
<div class="happy-css">
</div>
@Html.EndForm()

看起来很愚蠢吗?是啊,各有各的好。我想了解它为什么会这样工作,并按照我的喜好塑造它。所以我认为我要开始挖掘的第一个地方是 MVC 3.0 源代码本身。所以我跳进 codeplex 来寻找 BeginForm 扩展方法。

( http://aspnet.codeplex.com/SourceControl/changeset/view/63452# 288009

所以现在我对如何开始实现我的目标有点困惑。通读代码,我发现它们都归结为一个根方法(这并不奇怪,因为大多数扩展方法似乎都是分层方法,所有方法都深入到单个方法以避免冗余)。

private static MvcForm FormHelper(this HtmlHelper htmlHelper, string formAction, FormMethod method, IDictionary<string, object> htmlAttributes) {
            TagBuilder tagBuilder = new TagBuilder("form");
            tagBuilder.MergeAttributes(htmlAttributes);
            // action is implicitly generated, so htmlAttributes take precedence.
            tagBuilder.MergeAttribute("action", formAction);
            // method is an explicit parameter, so it takes precedence over the htmlAttributes.
            tagBuilder.MergeAttribute("method", HtmlHelper.GetFormMethodString(method), true);

            HttpResponseBase httpResponse = htmlHelper.ViewContext.HttpContext.Response;
            httpResponse.Write(tagBuilder.ToString(TagRenderMode.StartTag));
            return new MvcForm(htmlHelper.ViewContext.HttpContext.Response);
        }

我在这里没有看到这个方法与不显眼的 javascript 之间的关系。如果我只是输入 ..

然后像这样输入我的验证...

@Html.ValidationSummary (false)

我没有得到不引人注目的 JavaScript。但如果我使用

@using (Html.BeginForm()) { 那么我就会这样做。我什至检查了生成的标记,但我真的找不到区别。

现在事情就变得奇怪了。如果我只是输入...

@Html.BeginForm() 然后输入我的所有表单代码,表单工作并且我得到了不显眼的javascript,但是我有在末尾手动输入 @Html.EndForm() 不起作用。但最重要的是,我现在将文本 System.Web.Mvc.Html.MvcForm 写入

html.

有人可以启发和/或帮助我吗?

This is going to seem like a bit of a silly endeavor, but it's something I want to learn nonetheless.

Right now, in ASP.NET MVC 3.0, you need to use the syntax @using (Html.BeginForm()) { and then later, the } to close a form block to get the fancy new 'unobtrusive javascript', lest you want to write all of it by hand (which is fine).

For some reason (Read: *OCD*) I don't like that. I'd really rather do this..

@Html.BeginForm()
<div class="happy-css">
</div>
@Html.EndForm()

Seem stupid yet? Yeah, well to each their own. I want to understand why it is working how it is and mold it to my liking. So I thought the first place I would start digging is the MVC 3.0 source itself. So I jumped into codeplex to find the BeginForm Extension method.

( http://aspnet.codeplex.com/SourceControl/changeset/view/63452#288009 )

So now I am a little confused as to how to begin achieving my goal. Reading through the code, I discovered that they all go down to a root method (not surprising, as most extension methods seem to be hierarchical methods all reaching down into a single one to avoid redundancy).

private static MvcForm FormHelper(this HtmlHelper htmlHelper, string formAction, FormMethod method, IDictionary<string, object> htmlAttributes) {
            TagBuilder tagBuilder = new TagBuilder("form");
            tagBuilder.MergeAttributes(htmlAttributes);
            // action is implicitly generated, so htmlAttributes take precedence.
            tagBuilder.MergeAttribute("action", formAction);
            // method is an explicit parameter, so it takes precedence over the htmlAttributes.
            tagBuilder.MergeAttribute("method", HtmlHelper.GetFormMethodString(method), true);

            HttpResponseBase httpResponse = htmlHelper.ViewContext.HttpContext.Response;
            httpResponse.Write(tagBuilder.ToString(TagRenderMode.StartTag));
            return new MvcForm(htmlHelper.ViewContext.HttpContext.Response);
        }

What I am not seeing here is how this method relates to the unobtrusive javascript. If I simply type out ..

<form action="/Controller/Action" method="post">

and then put in my validation like so...

@Html.ValidationSummary(false)

I do not get the unobtrusive javascript. But if I use

@using (Html.BeginForm()) { then I do. I've even examined the generated markup and I really can't find the difference.

Now then it gets strange. If I just type in ...

@Html.BeginForm() and then put all of my form code, the form works and I get the unobtrusive javascript, but I have to manually type in </form> at the end. @Html.EndForm() doesn't work. But ontop of that, I now get the text System.Web.Mvc.Html.MvcForm written to the output stream right beneath the <form action="/Controller/Action" method="post"> html.

Can someone enlighten and/or help me?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

只有影子陪我不离不弃 2024-10-25 13:12:56

您的根本问题(即如何使用 BeginForm/EndForm 语法)的答案是按以下方式执行:

@{ Html.BeginForm(...); }
<div> content</div>
@{ Html.EndForm(); }

不幸的是,在调用写入输出的帮助程序时,现在的 Razor 语法有点冗长(与大多数情况相反)只返回 html 片段的助手)。您可以通过编写自己的扩展方法来使这变得更容易,如下所示:

public static IHtmlString FormBegin(this HtmlHelper helper, ...) {
    helper.BeginForm(...);
    return new HtmlString("");
}

public static IHtmlString FormEnd(this HtmlHelper helper) {
    helper.EndForm();
    return new HtmlString("");
}

The answer to your underlying question (i.e. how to use BeginForm/EndForm syntax) is to do it in the following manner:

@{ Html.BeginForm(...); }
<div> content</div>
@{ Html.EndForm(); }

Unfortunately the Razor syntax right now is a bit more verbose when invoking helpers that write to the output (as opposed to the majority of helpers which just return an html snippet). You could probably make this easier by writing your own extension methods like so:

public static IHtmlString FormBegin(this HtmlHelper helper, ...) {
    helper.BeginForm(...);
    return new HtmlString("");
}

public static IHtmlString FormEnd(this HtmlHelper helper) {
    helper.EndForm();
    return new HtmlString("");
}
公布 2024-10-25 13:12:56

我认为它起作用的原因是 BeginForm 方法返回一个 MvcForm 对象而不是 html,它将 html 直接写入页面。当 using 块结束时,它会被释放并写入结束结束标记。这就是您在输出中看到文本 System.Web.Mvc.Html.MvcForm 的原因。您必须手动将结束标记放在那里,因为 MvcForm 对象没有被释放。

使用语法就像这样做:

@{ MvcForm mf = Html.BeginForm(); /* writes directly to html stream */ }
<div class="happy-css">
</div>
@{ mf.Dispose(); /* like calling mf.EndForm() */ }

The reason it works I believe is that the BeginForm method returns an MvcForm object and not html, it writes the html directly to the page. When the using block ends it is disposed and it writes the closing end tag. That's the reason you see the text System.Web.Mvc.Html.MvcForm appear in your output. You have to put the closing tag in there manually because the MvcForm object isn't disposed.

The using syntax is like doing this:

@{ MvcForm mf = Html.BeginForm(); /* writes directly to html stream */ }
<div class="happy-css">
</div>
@{ mf.Dispose(); /* like calling mf.EndForm() */ }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文