ASP.NET MVC 3:当 BeginForm 位于布局上时生成不显眼的验证

发布于 2024-10-17 15:43:11 字数 395 浏览 6 评论 0原文

我刚刚意识到,当我在布局页面上围绕 RenderBody 部分放置表单标记时,不会生成不显眼的验证。像这样的事情:

@using (Html.BeginForm())
{
    <input type="submit" value="save" />

    <div>
        @RenderBody()
    </div>
}

正如您可能已经猜到的,我想在我的内容上生成按钮。这是正确的不引人注目的行为吗?

顺便说一句,如果我将表单放置在特定页面内,一切都会像魅力一样工作: data-val* 属性生成良好。

我将感谢您的宝贵帮助。

最好的问候

罗德里戈

I just realized that when I place a form tag on my layout page, surrounding the RenderBody section, the unobtrusive validation is not being generated. Something like this:

@using (Html.BeginForm())
{
    <input type="submit" value="save" />

    <div>
        @RenderBody()
    </div>
}

As you might have guessed I want to generate buttons over my content. Is this the correct unobtrusive's behavior?

BTW, If I place the form inside a particular page, everything works like a charm: the data-val* attributes are well generated.

I'll appreciate your valuable help.

best regards

Rodrigo

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

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

发布评论

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

评论(5

裸钻 2024-10-24 15:43:11

你可以在你的视图中应用一个怪诞的黑客:

@{
    var originalContext = ViewContext.FormContext;
    ViewContext.FormContext = new FormContext();
}

<!-- This will generate proper HTML5 data-* validation attributes -->
@Html.TextBoxFor(x => x.Prop1)
@Html.ValidationMessageFor(x => x.Prop1)

@Html.TextBoxFor(x => x.Prop2)
@Html.ValidationMessageFor(x => x.Prop2)

@{
    ViewContext.FormContext = originalContext;
}

You could apply a grotesque hack inside your view:

@{
    var originalContext = ViewContext.FormContext;
    ViewContext.FormContext = new FormContext();
}

<!-- This will generate proper HTML5 data-* validation attributes -->
@Html.TextBoxFor(x => x.Prop1)
@Html.ValidationMessageFor(x => x.Prop1)

@Html.TextBoxFor(x => x.Prop2)
@Html.ValidationMessageFor(x => x.Prop2)

@{
    ViewContext.FormContext = originalContext;
}
じ违心 2024-10-24 15:43:11

虽然将 @using (Html.BeginForm()) 放入内容页面可以修复验证问题,但它还会将一组额外的

标记放入输出中。我创建了一个小扩展来解决问题,而无需向输出写入任何内容。

将其用作 @using (Html.BeginSubForm())

public static class FormExtensions
{
    public static MvcSubForm BeginSubForm(this HtmlHelper html)
    {
        return new MvcSubForm(html.ViewContext);
    }
}


public sealed class MvcSubForm : IDisposable
{
    private readonly ViewContext _viewContext;
    private readonly FormContext _originalFormContext;

    public MvcSubForm(ViewContext viewContext)
    {
        _viewContext = viewContext;
        _originalFormContext = viewContext.FormContext;

        viewContext.FormContext = new FormContext();
    }


    public void Dispose()
    {
        if (_viewContext != null)
        {
            _viewContext.FormContext = _originalFormContext;
        }
    }
}

While putting @using (Html.BeginForm()) into the content page fixes the validation problem it also puts an extra set of <form> tags into the output. I created a small extension that fixes the problem without writing anything to the output.

Use it as @using (Html.BeginSubForm())

public static class FormExtensions
{
    public static MvcSubForm BeginSubForm(this HtmlHelper html)
    {
        return new MvcSubForm(html.ViewContext);
    }
}


public sealed class MvcSubForm : IDisposable
{
    private readonly ViewContext _viewContext;
    private readonly FormContext _originalFormContext;

    public MvcSubForm(ViewContext viewContext)
    {
        _viewContext = viewContext;
        _originalFormContext = viewContext.FormContext;

        viewContext.FormContext = new FormContext();
    }


    public void Dispose()
    {
        if (_viewContext != null)
        {
            _viewContext.FormContext = _originalFormContext;
        }
    }
}
逐鹿 2024-10-24 15:43:11

感谢您的帮助,我尝试了,但我找到了一个不像您建议的那样“怪诞”(如您所说)的解决方案:D

我只是在我的页面中放置了一个 BeginForm 方法,并在布局上放置了一个 BeginForm 方法:

@* On the layout page *@
@using (Html.BeginForm())
{
    <input type="submit" value="save" />

    <div>
        @RenderBody()
    </div>
}


@* On the content page *@
@using(Html.BeginForm())
{
  @* Content *@
}

所以,在我有两个 BeginForm 方法:ASP.NET MVC 引擎正在使用位于布局页面上的方法,因此 data-val* 属性能够正确呈现,并且表单放置在我想要的位置,因此布局上的任何提交按钮都可以提交我的特定页面并进行验证

它效果很好

非常感谢


罗德里戈

Thanks for your help, I tried it but I found a solution not as "grotesque" (as you said) as you suggested :D

I simply put a BeginForm method inside my page and also a BeginForm method on the layout:

@* On the layout page *@
@using (Html.BeginForm())
{
    <input type="submit" value="save" />

    <div>
        @RenderBody()
    </div>
}


@* On the content page *@
@using(Html.BeginForm())
{
  @* Content *@
}

so, at the end I have two BeginForm methods: ASP.NET MVC engine is using the one located on the layout page, so the data-val* attributes are being rendered correctly and the form is placed just where I wanted so any submit button on the layout can submit my particular page with the validations rendered

It works pretty well

Thanks a lot

regards,
Rodrigo

⒈起吃苦の倖褔 2024-10-24 15:43:11

我刚刚遇到了同样的问题,但可能是基于 达林·季米特洛夫的答案。

诀窍是基于 WebViewPage类,视图的默认基类,并执行 FormContext 在那里交换。

abstract public class FormFixWebViewPage : FormFixWebViewPage<object>
{
}

abstract public class FormFixWebViewPage<T> : WebViewPage<T>
{
    override public void Write(System.Web.WebPages.HelperResult result)
    {
        var originalFormContext = ViewContext.FormContext;
        ViewContext.FormContext = new FormContext();

        base.Write(result);

        ViewContext.FormContext = originalFormContext;
    }
}

然后在 ~/Views/ 文件夹下的 Web.config 文件中,更改 pages 下的 pageBaseType 属性元素,可以在 system.web.webPages.razor 部分找到:

<system.web.webPages.razor>
    <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    <pages pageBaseType="<YOUR-NAMESPACE>.FormFixWebViewPage">
    <!--pages pageBaseType="System.Web.Mvc.WebViewPage"-->
        <namespaces>
            <add namespace="System.Web.Mvc" />
            <add namespace="System.Web.Mvc.Ajax" />
            <add namespace="System.Web.Mvc.Html" />
            <add namespace="System.Web.Helpers" />
            <add namespace="System.Web.Routing" />
        </namespaces>
    </pages>
</system.web.webPages.razor>

I've just run into the same problem, but possibly a better solution based on Darin Dimitrov's answer.

The trick is to create a page base type, based on the WebViewPage<T> class, the default base class for views and do the FormContext swap there.

abstract public class FormFixWebViewPage : FormFixWebViewPage<object>
{
}

abstract public class FormFixWebViewPage<T> : WebViewPage<T>
{
    override public void Write(System.Web.WebPages.HelperResult result)
    {
        var originalFormContext = ViewContext.FormContext;
        ViewContext.FormContext = new FormContext();

        base.Write(result);

        ViewContext.FormContext = originalFormContext;
    }
}

And then in the Web.config file under the ~/Views/ folder, alter the pageBaseType attribute under pages element, which can be found in the system.web.webPages.razor section:

<system.web.webPages.razor>
    <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    <pages pageBaseType="<YOUR-NAMESPACE>.FormFixWebViewPage">
    <!--pages pageBaseType="System.Web.Mvc.WebViewPage"-->
        <namespaces>
            <add namespace="System.Web.Mvc" />
            <add namespace="System.Web.Mvc.Ajax" />
            <add namespace="System.Web.Mvc.Html" />
            <add namespace="System.Web.Helpers" />
            <add namespace="System.Web.Routing" />
        </namespaces>
    </pages>
</system.web.webPages.razor>
∞觅青森が 2024-10-24 15:43:11

只需在子视图文件顶部添加以下代码...

@{
   Layout = "~/Views/Shared/_Layout.cshtml";
   this.ViewContext.FormContext = new FormContext();
}

它对我来说工作正常。

我希望这能帮助你......

Just add below code at top of the child view file...

@{
   Layout = "~/Views/Shared/_Layout.cshtml";
   this.ViewContext.FormContext = new FormContext();
}

its working fine for me.

i hope this will help you....

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文