TonyG
TonyG

Reputation: 1675

Html.BeginForm in MVC3 is rendering too much

I have the following code. Note that I am not using a using as I want to begin and end the form in two different areas of my code. Has anyone seen this action where the helper adds "System.Web.Mvc.Html.MvcForm". I cannot see why this is added.

Code:
 @Html.BeginForm(new { action = ViewContext.Controller.ValueProvider.GetValue("action").RawValue })

@{ Html.EndForm() }

Result:
<form action="/adminTests/Edit" method="post">System.Web.Mvc.Html.MvcForm

When I use the following I don't get the "System.Web.Mvc.Html.MvcForm"

    @using (Html.BeginForm(new { action = ViewContext.Controller.ValueProvider.GetValue("action").RawValue }))
    {

}

Upvotes: 0

Views: 4252

Answers (4)

Pat McGee
Pat McGee

Reputation: 1

I also saw System.Web.Mvc.Html.MvcForm when using:

Html.BeginForm("Index", "Home", FormMethod.Post)

The following change fixed it:

Html.BeginForm("Index", "Home", "POST");

Seems like FormMethod.Post forces the unwanted output but I can't explain it better than that. The change worked for me though.

Upvotes: 0

tvanfosson
tvanfosson

Reputation: 532435

You need to wrap that in a using statement. BeginForm writes directly to the response stream, it isn't intended to return a string like the other helpers. The way you are using it, it is writing it's output, then returning the MvcForm object which, when disposed, will write the closing form tag. Instead, your syntax forces it to call ToString on the returned object resulting in the output you see.

@using(Html.BeginForm(...
{
   ...
}

Edit: Since you can't wrap it in a using statement, you need to either explicitly close the form with HTML or call EndForm later. In either case you have to use the BeginForm (and EndForm) in a code block instead of using it with the string output syntax. Both of these methods write directly to the response stream.

@{ Html.BeginForm() ..  }

</form>  or   @{ Html.EndForm() }

Here's the relevant bits of the code for those who think I'm wrong (without permission):

public static void EndForm(this HtmlHelper htmlHelper) {
    HttpResponseBase httpResponse = htmlHelper.ViewContext.HttpContext.Response;
    httpResponse.Write("</form>");  // <-- look ma, Response.Write()
}

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)); <-- and here
    return new MvcForm(htmlHelper.ViewContext.HttpContext.Response);
}

Upvotes: 3

superlogical
superlogical

Reputation: 14950

Try something like this:

    @using (Html.BeginForm()) { 
    @Html.ValidationSummary(true)
    <fieldset>
        <p>
            @Html.LabelFor(model => model.Username) <br />
            @Html.EditorFor(model => model.Username)
            @Html.ValidationMessageFor(model => model.Username)
        </p>

        <p>
            @Html.LabelFor(model => model.Password) <br />
            @Html.EditorFor(model => model.Password) @Html.RouteLink("Forgot Password", "password") <br />
            @Html.ValidationMessageFor(model => model.Password)
        </p>

        <p class="mtop10">              
            <div class="float-left small blue super-button">
                <a class="auto-submit" href="#">Login</a>
            </div>
            <div class="alt-action">
                or @Html.RouteLink("Register", "register")
            </div>
        </p>

    </fieldset>
}

Upvotes: 0

Darin Dimitrov
Darin Dimitrov

Reputation: 1038720

The BeginForm/EndForm helpers don't return a IHtmlResult so you should use them like this:

@{ Html.BeginForm(new { action = ViewContext.Controller.ValueProvider.GetValue("action").RawValue }); }

    ...

@{ Html.EndForm(); }

Upvotes: 1

Related Questions