Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET MVC - Post form to html bookmark?

Tags:

asp.net-mvc

When using a form like this:

<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>

I need the page to scroll to #errors when it posts. The Model.EulaHtml contains some length EULA text and I'd prefer that the user not have to manually scroll down to see an error message if they post the page without accepting the agreement.

If the controller detects ModelState.IsValid on Post, it redirects to another page. If not, I need to stay on this page, but scroll to the #errors bookmark anchor tag.

I've thought about just adding '#errors' to the end of the url in the form action, but I receive errors along the line of a potentially dangerous .... ('%'). It's possible that I'm incorrectly encoding the hash mark. Anyone else had to deal with this? We're dealing with pretty restrictive requirements for browser compatibility (IE6+ and everything else under the sun) so I try to avoid using JavaScript whenever possible.

Update

The error I'm receiving is:

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

I modifed the Html.BeginForm() call to

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

And the resulting URL is:

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

I also noticed that a few queryString parameters that were being passed through disappear when I set the action attribute in this way. (Not surprising, but no fix for that is immediately obvious to me)

like image 436
3Dave Avatar asked Dec 13 '22 17:12

3Dave


2 Answers

Try like this:

<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>

You could also write a custom HTML helper that will do the job:

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);
    }
}

And then:

<% using (Html.MyBeginForm("index", "home", "errors")) { %>
    ...
<% }
like image 158
Darin Dimitrov Avatar answered Jan 20 '23 09:01

Darin Dimitrov


Updated MVC 4 solution to the problem:

 @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 will generate the validation attributes in your form, using the html <form> tag will not.

This call is using the Html.BeginForm(actionName, controllerName, routeValues, FormMethod, htmlAttributes) overload, nulling all the routing and assigning the action as an html attribute instead. The routing is accomplished by using Url.Action(), to which I append my bookmark.

like image 39
gabnaim Avatar answered Jan 20 '23 10:01

gabnaim