ASP.NET MVC - 将表单发布到html书签?

时间:2010-12-09 10:29:38

标签: asp.net-mvc

使用这样的表格时:

<h2>
<%:Model.EulaTitle %>
</h2>
<p>
<%=Model.EulaHtml %>
</p>
<a name="errors"></a>
<%:Html.ValidationSummary()%>


<div style="text-align:center;">
<% using (Html.BeginForm())
   { %>

<%:Html.HiddenFor(model => model.SourceUrl)%>
<%:Html.HiddenFor(model => model.EulaId)%>


<a name="accept"></a>
<div style="text-align:center;">
<%:Html.CheckBoxFor(model => model.Accepted)%>
<%:Html.LabelFor(model => model.Accepted)%>
</div>
<input type="submit" value="Submit">
<% } %>
</div>

我需要页面在发布时滚动到#errorsModel.EulaHtml包含一些长度的EULA文本,我更希望用户不必手动向下滚动以查看错误消息,如果他们发布页面而未接受协议。

如果控制器在Post上检测到ModelState.IsValid,它会重定向到另一个页面。如果没有,我需要留在此页面,但滚动到#errors书签锚标记。

我已经考虑过在表单操作中将“#errors”添加到url的末尾,但是我会在a potentially dangerous .... ('%')的行中收到错误。我可能错误地编码了哈希标记。其他人不得不处理这个?我们正在处理对浏览器兼容性(IE6 +以及其他所有其他方面)的限制性要求,因此我尽量避免使用JavaScript。

更新

我收到的错误是:

A potentially dangerous Request.Path value was detected from the client (%).

我修改了Html.BeginForm()

的调用
<% using (Html.BeginForm(new { @action="#errors" }))
   { %>

结果网址为:

http://..../TheControllerName/Eula/%2523errors/

我还注意到,当我以这种方式设置action属性时,传递的一些queryString参数消失了。 (这并不奇怪,但对我来说没有任何解决方法对我来说很明显)

3 个答案:

答案 0 :(得分:6)

试试这样:

<form action="<%: Url.Action("actionName", "controllerName") %>#errors" method="post">

    <%:Html.HiddenFor(model => model.SourceUrl)%>
    <%:Html.HiddenFor(model => model.EulaId)%>


    <a name="accept"></a>
    <div style="text-align:center;">
    <%:Html.CheckBoxFor(model => model.Accepted)%>
    <%:Html.LabelFor(model => model.Accepted)%>
    </div>
    <input type="submit" value="Submit">

</form>

您还可以编写一个可以执行此任务的自定义HTML帮助程序:

public static class FormExtensions
{
    public static MvcForm MyBeginForm(this HtmlHelper htmlHelper, string actionName, string controllerName, string fragment)
    {
        var formAction = UrlHelper.GenerateUrl(null, actionName, controllerName, htmlHelper.ViewContext.HttpContext.Request.Url.Scheme, null, fragment, null, htmlHelper.RouteCollection, htmlHelper.ViewContext.RequestContext, true);
        var builder = new TagBuilder("form");
        builder.MergeAttribute("action", formAction);
        builder.MergeAttribute("method", "post", true);
        htmlHelper.ViewContext.Writer.Write(builder.ToString(TagRenderMode.StartTag));
        return new MvcForm(htmlHelper.ViewContext);
    }
}

然后:

<% using (Html.MyBeginForm("index", "home", "errors")) { %>
    ...
<% }

答案 1 :(得分:5)

更新了问题的MVC 4解决方案:

 @using (Html.BeginForm(null, null, null, FormMethod.Post,
     new
        {
            @action = Url.Action("MyAction") + "#bookmark",
            @class = "form-class",
            target = "_blank"
        }))
 {
     ... 
     <input type="submit" value="submit" />

 }

Html.BeginForm将在您的表单中生成验证属性,而不会使用html <form>标记。

此调用使用Html.BeginForm(actionName, controllerName, routeValues, FormMethod, htmlAttributes)重载,将所有路由归零并将操作指定为html属性。路由是通过使用Url.Action()完​​成的,我附加了我的书签。

答案 2 :(得分:1)

我想出了一个与此不同的解决方案,使用动作过滤器:

http://spikehd.blogspot.com/2012/01/mvc3-redirect-action-to-html-bookmark.html

它修改HTML缓冲区并输出一小段javascript来指示浏览器附加书签。

希望有所帮助:)