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

时间:2011-02-14 21:06:37

标签: asp.net-mvc-3 unobtrusive-validation

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

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

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

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

BTW,如果我将表单放在特定页面中,一切都像魅力一样:data-val *属性生成良好。

我将非常感谢您的宝贵帮助。

最好的问候

罗德里戈

5 个答案:

答案 0 :(得分:12)

你可以在视图中应用怪诞的黑客攻击:

@{
    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;
}

答案 1 :(得分:4)

虽然将@using (Html.BeginForm())放入内容页面可修复验证问题,但它还会在输出中添加一组额外的<form>标记。我创建了一个小扩展,可以解决问题,而无需在输出中写入任何内容。

将其用作@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;
        }
    }
}

答案 2 :(得分:1)

感谢您的帮助,我尝试了但是我找到了一个解决方案而不是像您所说的那样“怪诞”(正如您所说):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 *属性正在正确呈现,表单放在我想要的位置布局上的任何提交按钮都可以使用提交的验证提交我的特定页面

效果很好

非常感谢

的问候, 的罗德里戈

答案 3 :(得分:1)

我遇到了同样的问题,但可能是基于Darin Dimitrov's回答的更好的解决方案。

诀窍是基于WebViewPage<T>类创建页面基类型,这是视图的默认基类,并在那里进行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;
    }
}

然后在Web.config文件夹下的~/Views/文件中,更改pageBaseType元素下的pages属性,该属性可在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>

答案 4 :(得分:1)

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

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

它对我来说很好。

我希望这会对你有帮助....