2012-03-01 4 views
3

ASP.NET MVC 면도기 페이지에 양식이 필요합니다. 내 기본 설정은 다음 구문을 사용하는 것입니다.HTML 속성을 Html.BeginForm()에 추가 할 때의 변형

@using (Html.BeginForm()) 
{ 
} 

그러나 양식에 여러 특성이 추가되어야합니다. 그래서 나는 다음과 같은 것으로 끝을 맺었다 :

@using (Html.BeginForm(null, null, FormMethod.Post, new { name = "value" })) 
{ 
} 

그러나 이것은 바람직하지 않은 부작용을 가지고있다. 이 페이지의 요청에 쿼리 인수가있는 경우 첫 번째 양식은 양식이 제출 될 때이를 전달합니다. 그러나 두 번째 버전은 그렇지 않습니다.

나는 왜 BeginForm()이 속성을 지원하지 않는지 정말로 모르지만 BeginForm()에 속성을 추가하는 간단한 방법이 있으며 for가 제출 될 때 여전히 모든 쿼리 인수를 전달합니까?

편집 :이 구문을 사용하는 경우

<form action="@Request.RawUrl" method="post" name="value"> 
</form> 

그러나, 클라이언트 측 유효성 검사가 비활성화 :

이에보고 후, 최고의 솔루션이 같은 것입니다 보인다. 더 복잡하고 잠재적으로 신뢰할 수없는 구조가 없으면이 상황에 대한 좋은 해결책이없는 것 같습니다.

답변

4
I는 내부 클라이언트 측 유효성 검사에 사용되는 형태의 컨텍스트를 유지하기 위해 사용자 정의 도우미와 함께 갈 것 참으로 사실이지만

:

public static class FormExtensions 
{ 
    private static object _lastFormNumKey = new object(); 

    public static IDisposable BeginForm(this HtmlHelper htmlHelper, object htmlAttributes) 
    { 
     string rawUrl = htmlHelper.ViewContext.HttpContext.Request.RawUrl; 
     return htmlHelper.FormHelper(rawUrl, FormMethod.Post, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes)); 
    } 

    private static int IncrementFormCount(IDictionary items) 
    { 
     object obj2 = items[_lastFormNumKey]; 
     int num = (obj2 != null) ? (((int)obj2) + 1) : 0; 
     items[_lastFormNumKey] = num; 
     return num; 
    } 

    private static string DefaultFormIdGenerator(this HtmlHelper htmlhelper) 
    { 
     int num = IncrementFormCount(htmlhelper.ViewContext.HttpContext.Items); 
     return string.Format(CultureInfo.InvariantCulture, "form{0}", new object[] { num }); 
    } 

    private static IDisposable FormHelper(this HtmlHelper htmlHelper, string formAction, FormMethod method, IDictionary<string, object> htmlAttributes) 
    { 
     var builder = new TagBuilder("form"); 
     builder.MergeAttributes<string, object>(htmlAttributes); 
     builder.MergeAttribute("action", formAction); 
     builder.MergeAttribute("method", HtmlHelper.GetFormMethodString(method), true); 
     bool flag = htmlHelper.ViewContext.ClientValidationEnabled && !htmlHelper.ViewContext.UnobtrusiveJavaScriptEnabled; 
     if (flag) 
     { 
      builder.GenerateId(htmlHelper.DefaultFormIdGenerator()); 
     } 
     htmlHelper.ViewContext.Writer.Write(builder.ToString(TagRenderMode.StartTag)); 
     var form = new MvcForm(htmlHelper.ViewContext); 
     if (flag) 
     { 
      htmlHelper.ViewContext.FormContext.FormId = builder.Attributes["id"]; 
     } 
     return form; 
    } 
} 

과 같이 사용될 수있다 :

@using (Html.BeginForm(htmlAttributes: new { name = "value" })) 
{ 
    ... 
} 
+0

감사 @Darin . 'IncrementFormCount','DefaultFormIdGenerator','FormHelper'가 무엇을하는지 조금 설명해 주시겠습니까? –

+0

@JonathanWood, FormHelper는 TagBuilders를 사용하여 '

'요소를 생성합니다. DefaultFormIdGenerator는 기본적으로 HttpContext에 카운트를 저장하고 매번 증가시킴으로써 주어진 뷰에서 렌더링 된 폼의 수를 추적합니다. 기본적으로 form0, form1, form2 ...와 같은 양식 ID를 가질 수 있습니다.이 양식 ID는 눈에 거슬리는 클라이언트 측 유효성 검사에서 사용됩니다. –

+0

감사. 그것은 작동하는 것 같습니다. 그러나 받아 들일 수있는'BeginForm()'버전과의 모호함을 피하기 위해 사용법을'@using (Html.BeginForm (HtmlHelper.AnonymousObjectToHtmlAttributes (new {@class = "form-horizontal"}))) 그냥 경로 값. –

1

비슷한 문제가 있었는데 여기에 빠른 해결책이 있습니다 (MVC4에서 작동 함).

확장 방법 선언 :

public static MvcForm BeginForm(this HtmlHelper helper, object htmlAttributes) 
{ 
     return helper.BeginForm(helper.ViewContext.RouteData.Values["Action"].ToString(), 
           helper.ViewContext.RouteData.Values["Controller"].ToString(), 
           FormMethod.Post, htmlAttributes); 
} 

및 페이지에서 사용 :

@using (Html.BeginForm(htmlAttributes: new {@class="form-horizontal"})) 
{ 
... 
} 
+2

이 방법을 사용하여 모든 쿼리 문자열을 잃어 버립니다. –

0
소스 코드에

작은 수정 :

http://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/Html/FormExtensions.cs

public static MvcForm BeginForm(this HtmlHelper htmlHelper, object htmlAttributes) 
{ 
    // generates <form action="{current url}" method="post">...</form> 
    string formAction = htmlHelper.ViewContext.HttpContext.Request.RawUrl; 
    return FormHelper(htmlHelper, formAction, FormMethod.Post, new RouteValueDictionary(htmlAttributes)); 
} 

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

    bool traditionalJavascriptEnabled = htmlHelper.ViewContext.ClientValidationEnabled 
             && !htmlHelper.ViewContext.UnobtrusiveJavaScriptEnabled; 

    if (traditionalJavascriptEnabled) 
    { 
     // forms must have an ID for client validation 
     tagBuilder.GenerateId(htmlHelper.ViewContext.FormIdGenerator()); 
    } 

    htmlHelper.ViewContext.Writer.Write(tagBuilder.ToString(TagRenderMode.StartTag)); 
    MvcForm theForm = new MvcForm(htmlHelper.ViewContext); 

    if (traditionalJavascriptEnabled) 
    { 
     htmlHelper.ViewContext.FormContext.FormId = tagBuilder.Attributes["id"]; 
    } 

    return theForm; 
} 
+0

'ViewContext.FormIdGenerator()'는 내부적입니다. :-( –

관련 문제