html - 특성 - ASP.NET MVC 프레임 워크에서 여러 제출 단추를 어떻게 처리합니까?




packagereference 요소 의 version 특성 을 인식 할 수 없습니다 (20)

ActionSelectName에 대해 마음에 들지 않는 부분은 IsValidName이 컨트롤러의 모든 작업 메서드에 호출된다는 것입니다. 왜 이런 식으로 작동하는지 모르겠습니다. 나는 모든 버튼이 무엇을 기반으로하는 다른 이름을 가진 솔루션을 좋아하지만, 폼의 버튼처럼 액션 메소드에서 많은 매개 변수를 가져야한다는 사실을 좋아하지 않는다. 모든 버튼 유형에 대해 enum을 만들었습니다.

public enum ButtonType
{
    Submit,
    Cancel,
    Delete
}

ActionSelectName 대신 ActionFilter를 사용합니다.

public class MultipleButtonsEnumAttribute : ActionFilterAttribute
{
    public Type EnumType { get; set; }

    public MultipleButtonsEnumAttribute(Type enumType)
    {
        EnumType = enumType;
    }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        foreach (var key in filterContext.HttpContext.Request.Form.AllKeys)
        {
            if (Enum.IsDefined(EnumType, key))
            {
                var pDesc = filterContext.ActionDescriptor.GetParameters()
                    .FirstOrDefault(x => x.ParameterType == EnumType);
                filterContext.ActionParameters[pDesc.ParameterName] = Enum.Parse(EnumType, key);
                break;
            }
        }
    }
}

필터는 양식 데이터에서 버튼 이름을 찾고 버튼 이름이 열거 형에 정의 된 버튼 유형 중 하나와 일치하면 액션 매개 변수 중에서 ButtonType 매개 변수를 찾습니다.

[MultipleButtonsEnumAttribute(typeof(ButtonType))]
public ActionResult Manage(ButtonType buttonPressed, ManageViewModel model)
{
    if (button == ButtonType.Cancel)
    {
        return RedirectToAction("Index", "Home");
    }
    //and so on
    return View(model)
}

보기에서 다음을 사용할 수 있습니다.

<input type="submit" value="Button Cancel" name="@ButtonType.Cancel" />
<input type="submit" value="Button Submit" name="@ButtonType.Submit" />

같은 양식에서 여러 제출 버튼을 처리하는 쉬운 방법이 있습니까? 예:

<% Html.BeginForm("MyAction", "MyController", FormMethod.Post); %>
<input type="submit" value="Send" />
<input type="submit" value="Cancel" />
<% Html.EndForm(); %>

ASP.NET 프레임 워크 베타에서이 작업을 수행하는 방법에 대해 알고 싶습니다. 내가 봤던 모든 예제는 단일 버튼을 가지고있다.


Eilon은 다음과 같이 할 수 있다고 제안합니다.

두 개 이상의 버튼이있는 경우 각 버튼에 이름을 지정하여 두 버튼을 구별 할 수 있습니다.

<input type="submit" name="SaveButton" value="Save data" />
<input type="submit" name="CancelButton" value="Cancel and go back to main page" />

컨트롤러 액션 메소드에서 HTML 입력 태그 이름 다음에 명명 된 매개 변수를 추가 할 수 있습니다.

public ActionResult DoSomeStuff(string saveButton, string
cancelButton, ... other parameters ...)
{ ... }

어떤 값이 해당 매개 변수 중 하나에 게시되면 해당 버튼이 클릭 된 것입니다. 웹 브라우저는 클릭 버튼에 대한 값만 게시합니다. 다른 모든 값은 null입니다.

if (saveButton != null) { /* do save logic */ }
if (cancelButton != null) { /* do cancel logic */ }

할당 된 이름보다 변경 가능성이 높고 자바 스크립트가 활성화되지 않아도되는 제출 버튼의 value 속성에 의존하지 않으므로이 메소드가 마음에 들었습니다.

참조 : http://forums.asp.net/p/1369617/2865166.aspx#2865166


그것에 대해 게시물을 작성 : ASP.NET MVC와 함께 여러 제출 버튼 :

기본적으로 ActionMethodSelectorAttribute 를 사용하는 대신 ActionNameSelectorAttribute 를 사용하고 있습니다.이 액션 이름은 원하는대로 무엇이든 할 수 있습니다. 다행히 ActionNameSelectorAttribute 는 액션 이름을 지정하게 ActionNameSelectorAttribute 는 것이 아니라 현재 액션이 요청과 일치하는지 여부를 선택할 수 있습니다.

그래서 내 수업이 있습니다. (나는 그 이름을 너무 좋아하지 않는다.)

public class HttpParamActionAttribute : ActionNameSelectorAttribute {
    public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo) {
        if (actionName.Equals(methodInfo.Name, StringComparison.InvariantCultureIgnoreCase))
            return true;

        if (!actionName.Equals("Action", StringComparison.InvariantCultureIgnoreCase))
            return false;

        var request = controllerContext.RequestContext.HttpContext.Request;
        return request[methodInfo.Name] != null;
    }
} 

다음과 같이 폼을 정의하면됩니다 :

<% using (Html.BeginForm("Action", "Post")) { %>
  <!— …form fields… -->
  <input type="submit" name="saveDraft" value="Save Draft" />
  <input type="submit" name="publish" value="Publish" />
<% } %> 

두 가지 방법으로 제어 장치

public class PostController : Controller {
    [HttpParamAction]
    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult SaveDraft(…) {
        //…
    }

    [HttpParamAction]
    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Publish(…) {
        //…
    } 
}

보시다시피,이 속성에는 아무 것도 지정하지 않아도됩니다. 또한 단추의 이름은 메서드 이름으로 직접 변환됩니다. 또한 (나는 그걸 시도하지 않았다) 정상적인 행동으로 잘 작동해야하므로, 그들 중 누구에게나 직접 게시 할 수있다.


그것은 짧고 스위트입니다.

그것은 Jeroen Dop 에 의해 응답되었습니다.

<input type="submit" name="submitbutton1" value="submit1" />
<input type="submit" name="submitbutton2" value="submit2" />

코드 뒤에서 이런 식으로해라.

 if( Request.Form["submitbutton1"] != null)
{
    // Code for function 1
}
else if(Request.Form["submitButton2"] != null )
{
       // code for function 2
}

행운을 빕니다.


나는이 '문제'를 보았지만 name 속성을 추가함으로써 다소 논리적 인 해결책을 발견했다. 이 문제가 다른 언어로 떠 올랐습니다.

http://www.w3.org/TR/html401/interact/forms.html#h-17.13.2

  • ...
  • 양식에 두 개 이상의 제출 버튼이 포함되어있는 경우 활성화 된 제출 버튼 만 성공합니다.
  • ...

다음 코드 value 특성은 강력한 형식의 리소스 파일 또는 상수를 확인하는 추가 코드 가 필요 없이 변경, 지역화, 국제화 될 수 있습니다.

<% Html.BeginForm("MyAction", "MyController", FormMethod.Post); %>
<input type="submit" name="send" value="Send" />
<input type="submit" name="cancel" value="Cancel" />
<input type="submit" name="draft" value="Save as draft" />
<% Html.EndForm(); %>`

수신 측에서는 알려진 제출 유형이 null 이 아닌지 확인 null

public ActionResult YourAction(YourModel model) {

    if(Request["send"] != null) {

        // we got a send

    }else if(Request["cancel"]) {

        // we got a cancel, but would you really want to post data for this?

    }else if(Request["draft"]) {

        // we got a draft

    }

}

다음과 같이 작성할 수 있습니다.

<% Html.BeginForm("MyAction", "MyController", FormMethod.Post); %>
<input type="submit" name="button" value="Send" />
<input type="submit" name="button" value="Cancel" />
<% Html.EndForm(); %>

그리고 페이지에서 이름 == "보내기"또는 이름 == "취소"가 있는지 확인하십시오.


다음은 여러 이미지 및 / 또는 텍스트 버튼을 처리하기 위해 작성한 확장 메소드입니다.

이미지 버튼 용 HTML은 다음과 같습니다.

<input id="btnJoin" name="Join" src="/content/images/buttons/btnJoin.png" 
       type="image">

또는 텍스트 제출 버튼 :

<input type="submit" class="ui-button green" name="Submit_Join" value="Add to cart"  />
<input type="submit" class="ui-button red" name="Submit_Skip" value="Not today"  />

다음은 form.GetSubmitButtonName() 을 사용하여 컨트롤러에서 호출하는 확장 메서드입니다. 이미지 단추의 경우 .x (이미지 단추가 클릭되었음을 나타내는)와 함께 양식 매개 변수를 찾고 이름을 추출합니다. 일반 input 버튼의 경우 Submit_ 시작하는 이름을 Submit_ 나중에 명령을 추출합니다. "명령"을 결정하는 논리를 추상화하고 있기 때문에 서버 측 코드를 변경하지 않고 클라이언트의 이미지 + 텍스트 단추를 전환 할 수 있습니다.

public static class FormCollectionExtensions
{
    public static string GetSubmitButtonName(this FormCollection formCollection)
    {
        return GetSubmitButtonName(formCollection, true);
    }

    public static string GetSubmitButtonName(this FormCollection formCollection, bool throwOnError)
    {
        var imageButton = formCollection.Keys.OfType<string>().Where(x => x.EndsWith(".x")).SingleOrDefault();
        var textButton = formCollection.Keys.OfType<string>().Where(x => x.StartsWith("Submit_")).SingleOrDefault();

        if (textButton != null)
        {
            return textButton.Substring("Submit_".Length);
        }

        // we got something like AddToCart.x
        if (imageButton != null)
        {
            return imageButton.Substring(0, imageButton.Length - 2);
        }

        if (throwOnError)
        {
            throw new ApplicationException("No button found");
        }
        else
        {
            return null;
        }
    }
}

참고 : 텍스트 버튼의 경우 이름 앞에 Submit_ 합니다. 이 방법을 선호하는 이유는 코드를 변경하지 않고 텍스트 (표시) 값을 변경할 수 있다는 것을 의미하기 때문입니다. SELECT 요소와 달리 INPUT 버튼에는 '값'만 있고 별도의 '텍스트'속성은 없습니다. 내 버튼은 상황에 따라 다른 것을 말하지만 동일한 '명령'에 매핑됩니다. 나는 == "Add to cart" 를 코드하는 것보다 이런 식으로 이름을 추출하는 것을 선호한다.


데이비드 핀 들리 (David Findley)는 자신의 ASP.Net 웹 로그에서이 작업에 대한 3 가지 옵션에 대해 씁니다.

기사를 읽으려면 동일한 양식의 여러 단추를 사용하여 그의 솔루션과 각각의 장단점을 확인하십시오. IMHO 그는 당신이 당신의 행동을 꾸미는 속성을 사용하는 매우 우아한 솔루션을 제공합니다.


버튼의 이름을 지정하고 값을 지정할 수 있어야합니다. 이 이름을 조치의 인수로 맵핑하십시오. 또는 2 개의 액션 링크 또는 2 개의 폼을 사용하십시오.


브라우저가 입력 버튼 (IE 10 이상, 다른 브라우저에 대해 확실하지 않음)에 대한 속성 양식을 지원하는 경우 다음이 작동합니다.

@using (Html.BeginForm()){
    //put form inputs here

<input id="sendBtn" value="Send" type="submit" formaction="@Url.Action("Name Of Send Action")" />

<input id="cancelBtn" value="Cancel" type="submit" formaction="@Url.Action("Name of Cancel Action") />

}

위의 문제를 해결할 수있는 세 가지 방법이 있습니다.

  1. HTML 방식
  2. Jquery 방식
  3. "ActionNameSelectorAttribute"방법

아래는 세 가지 방법을 모두 시범 적으로 요약 한 비디오입니다.

https://www.facebook.com/shivprasad.koirala/videos/vb.100002224977742/809335512483940

HTML 방식 : -

HTML 방식으로 두 가지 양식을 만들고 각 양식 안에 "제출"버튼을 배치해야합니다. 그리고 모든 양식의 행동은 다른 / 각각의 행동을 가리킬 것입니다. 첫 번째 양식이 "Action1"에 게시되고 두 번째 양식이 어떤 "제출"버튼을 클릭했는지에 따라 "Action2"에 게시하는 아래 코드를 볼 수 있습니다.

<form action="Action1" method=post>
<input type=”submit” name=”Submit1”/>
</form>

<form action="Action2" method=post>
<input type=”submit” name=”Submit2”>
</form>

아약스 방식 : -

당신이 Ajax 애호가 인 경우이 두 번째 옵션은 당신을 더 흥분시킬 것입니다. Ajax 방식에서는 "Fun1"과 "Fun1"의 두 가지 기능을 만들 수 있습니다. 아래 코드를 참조하십시오. 이 함수는 Jquery 또는 다른 프레임 워크를 사용하여 Ajax 호출을 작성합니다. 이러한 각 기능은 "제출"버튼의 "OnClick"이벤트와 바인드됩니다. 이 함수들 각각은 각각의 액션 이름을 호출합니다.

<Script language="javascript">
function Fun1()
{
$.post(“/Action1”,null,CallBack1);
}
function Fun2()
{
$.post(“/Action2”,null,CallBack2);
}
</Script>

<form action="/Action1" method=post>
<input type=submit name=sub1 onclick=”Fun2()”/>
</form>
<form action="/Action2" method=post>
<input type=submit name=sub2 onclick=”Fun1()”/>
</form>

"ActionNameSelectorAttribute"사용 : -

이것은 훌륭하고 깨끗한 선택입니다. "ActionNameSelectorAttribute"는 실행 가능한 액션을 결정하는 의사 결정 로직을 작성할 수있는 간단한 속성 클래스입니다.

그래서 HTML에서 첫 번째는 서버에서 식별하기 위해 submit 버튼에 적절한 이름을 넣어야한다는 것입니다.

버튼 이름에 "저장"및 "삭제"를 입력 한 것을 볼 수 있습니다. 또한 우리는 컨트롤러 이름 "고객"을 입력하고 특정 작업 이름이 아닌 작업을 확인할 수 있습니다. 액션 이름은 "ActionNameSelectorAttribute"에 의해 결정될 것으로 예상됩니다.

<form action=”Customer” method=post>
<input type=submit value="Save" name="Save" /> <br />
<input type=submit value="Delete" name="Delete"/>
</form>

따라서 제출 버튼을 클릭하면 먼저 "ActionNameSelector"속성에 도달 한 다음 어떤 제출이 시작되었는지에 따라 적절한 조치가 취해집니다.

그래서 첫 번째 단계는 "ActionNameSelectorAttribute"클래스에서 상속받은 클래스를 만드는 것입니다. 이 클래스에서는 간단한 "Name"속성을 만들었습니다.

True 또는 flase를 반환하는 "IsValidName"함수를 재정의해야합니다. 이 함수는 동작을 실행해야하는지 여부를 로직을 작성하는 곳입니다. 따라서이 함수가 true를 반환하면 액션이 실행되고 그렇지 않으면 실행되지 않습니다.

public class SubmitButtonSelector : ActionNameSelectorAttribute
    {
        public string Name { get; set; }
        public override bool IsValidName(ControllerContext controllerContext, string actionName, System.Reflection.MethodInfo methodInfo)
        {
            // Try to find out if the name exists in the data sent from form
var value = controllerContext.Controller.ValueProvider.GetValue(Name);
            if (value != null)
            {
                return true;
            }
            return false;

        }
    }

위의 함수의 핵심은 아래 코드에 있습니다. "ValueProvider"컬렉션에는 양식에서 게시 된 모든 데이터가 있습니다. 따라서 먼저 "Name"값을 찾고 HTTP 요청에서 발견되면 true를 반환하거나 그렇지 않으면 false를 반환합니다.

var value = controllerContext.Controller.ValueProvider.GetValue(Name);
if (value != null)
      {
        return true;
      }
      return false;

이 속성 클래스는 각각의 액션에 꾸밀 수 있으며 각각의 "Name"값을 제공 할 수 있습니다. 따라서 제출이이 작업을 수행하는 경우 HTML 제출 버튼 이름과 이름이 일치하면 작업을 더 실행하거나 그렇지 않으면 실행하지 않습니다.

public class CustomerController : Controller
{
        [SubmitButtonSelector(Name="Save")]
        public ActionResult Save()
        {
            return Content("Save Called");
        }
        [SubmitButtonSelector(Name = "Delete")]
        public ActionResult Delete()
        {
            return Content("Delete Called");
        }
}

이 스크립트는 모든 브라우저에서 HTML5 formaction 속성으로 작동 할 data-form-action 속성을 지정할 수 있습니다 (눈에 거슬리는 방식으로).

$(document).on('click', '[type="submit"][data-form-action]', function(event) {
    var $this = $(this),
    var formAction = $this.attr('data-form-action'),
    $form = $($this.closest('form'));
    $form.attr('action', formAction);             
});

버튼이 포함 된 양식은 data-form-action 속성에 지정된 URL에 게시됩니다.

<button type="submit" data-form-action="different/url">Submit</button>   

jquery 1.7이 필요합니다. 이전 버전에서는 on() 대신 live() 를 사용해야합니다.


이해 관계자 가 Maarten Balliauw의 솔루션을 살펴볼 것을 제안 합니다 . 나는 그것이 매우 우아하다고 생각한다.

링크가 사라지면 컨트롤러 동작에 적용된 MultiButton 특성을 사용하여 해당 동작을 클릭해야하는 버튼을 나타냅니다.


제출 버튼에 이름을 지정한 다음 컨트롤러 메소드에서 제출 된 값을 검사합니다.

<% Html.BeginForm("MyAction", "MyController", FormMethod.Post); %>
<input type="submit" name="submitButton" value="Send" />
<input type="submit" name="submitButton" value="Cancel" />
<% Html.EndForm(); %>

에 게시

public class MyController : Controller {
    public ActionResult MyAction(string submitButton) {
        switch(submitButton) {
            case "Send":
                // delegate sending to another controller action
                return(Send());
            case "Cancel":
                // call another action to perform the cancellation
                return(Cancel());
            default:
                // If they've submitted the form without a submitButton, 
                // just return the view again.
                return(View());
        }
    }

    private ActionResult Cancel() {
        // process the cancellation request here.
        return(View("Cancelled"));
    }

    private ActionResult Send() {
        // perform the actual send operation here.
        return(View("SendConfirmed"));
    }

}

편집하다:

지역화 된 사이트에서 작동하도록이 접근 방식을 확장하려면 다른 곳에서 메시지를 격리하십시오 (예 : 리소스 파일을 강력한 형식의 리소스 클래스로 컴파일)

그런 다음 코드가 다음과 같이 작동하도록 수정하십시오.

<% Html.BeginForm("MyAction", "MyController", FormMethod.Post); %>
<input type="submit" name="submitButton" value="<%= Html.Encode(Resources.Messages.Send)%>" />
<input type="submit" name="submitButton" value="<%=Html.Encode(Resources.Messages.Cancel)%>" />
<% Html.EndForm(); %>

귀하의 컨트롤러는 다음과 같이 보일 것입니다 :

// Note that the localized resources aren't constants, so 
// we can't use a switch statement.

if (submitButton == Resources.Messages.Send) { 
    // delegate sending to another controller action
    return(Send());

} else if (submitButton == Resources.Messages.Cancel) {
     // call another action to perform the cancellation
     return(Cancel());
}

이것이 내가 찾은 최선의 방법입니다.

http://iwayneo.blogspot.co.uk/2013/10/aspnet-mvc-action-selector-with-list.html

다음은 코드입니다.

    /// <summary>
    /// ActionMethodSelector to enable submit buttons to execute specific action methods.
    /// </summary>
    public class AcceptParameterAttribute : ActionMethodSelectorAttribute
   {
        /// <summary>
        /// Gets or sets the value to use to inject the index into
        /// </summary>
       public string TargetArgument { get; set; }

       /// <summary>
       /// Gets or sets the value to use in submit button to identify which method to select. This must be unique in each controller.
       /// </summary>
       public string Action { get; set; }

       /// <summary>
       /// Gets or sets the regular expression to match the action.
       /// </summary>
       public string ActionRegex { get; set; }

       /// <summary>
       /// Determines whether the action method selection is valid for the specified controller context.
       /// </summary>
       /// <param name="controllerContext">The controller context.</param>
       /// <param name="methodInfo">Information about the action method.</param>
       /// <returns>true if the action method selection is valid for the specified controller context; otherwise, false.</returns>
       public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo)
       {

           if (controllerContext == null)
           {
               throw new ArgumentNullException("controllerContext");
           }

           Func<NameValueCollection> formGetter;
           Func<NameValueCollection> queryStringGetter;

           ValidationUtility.GetUnvalidatedCollections(HttpContext.Current, out formGetter, out queryStringGetter);

           var form = formGetter();
           var queryString = queryStringGetter();

           var req = form.AllKeys.Any() ? form : queryString;

           if (!string.IsNullOrEmpty(this.ActionRegex))
           {
               foreach (var key in req.AllKeys.Where(k => k.StartsWith(Action, true, System.Threading.Thread.CurrentThread.CurrentCulture)))
               {
                   if (key.Contains(":"))
                   {
                       if (key.Split(':').Count() == this.ActionRegex.Split(':').Count())
                       {
                           bool match = false;
                           for (int i = 0; i < key.Split(':').Count(); i++)
                           {
                               if (Regex.IsMatch(key.Split(':')[0], this.ActionRegex.Split(':')[0]))
                               {
                                   match = true;
                               }
                               else
                               {
                                   match = false;
                                   break;
                               }
                           }

                           if (match)
                           {
                               return !string.IsNullOrEmpty(req[key]);
                           }
                       }
                   }
                   else
                   {
                       if (Regex.IsMatch(key, this.Action + this.ActionRegex))
                       {
                           return !string.IsNullOrEmpty(req[key]);
                       }
                   }

               }
               return false;
           }
           else
           {
               return req.AllKeys.Contains(this.Action);
           }
       }
   }

미래에 코드 - 냄새가없는 멀티 제출 버튼을 즐기십시오.

고맙습니다


제출 버튼마다 다음을 추가하십시오.

$('#btnSelector').click(function () {

    $('form').attr('action', "/Your/Action/);
    $('form').submit();

});

HttpParamActionAttribute만료 된 / 유효하지 않은 세션 포스트 백에서 오류가 발생하지 않도록 버그 수정 된 메소드의 수정 된 버전입니다 . 이것이 현재 사이트의 문제인지 확인하려면 창에서 양식을 열고 Save또는 을 클릭 하거나 Publish복제 창을 열고 로그 아웃 하기 직전에 양식을여십시오 . 이제 첫 번째 창으로 돌아가서 두 단추 중 하나를 사용하여 양식을 제출하십시오. 나를 위해이 변경이 나를 위해 그 문제를 해결할 수 있도록 오류가 발생했습니다. 나는 간결함을 위해서 많은 것들을 생략하지만 아이디어를 얻어야한다. 중요한 부분은 ActionName속성에 포함되어 전달 된 이름이 양식을 표시하는보기의 이름인지 확인하는 것입니다

속성 클래스

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class HttpParamActionAttribute : ActionNameSelectorAttribute
{
    private readonly string actionName;

    public HttpParamActionAttribute(string actionName)
    {
        this.actionName = actionName;
    }

    public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo)
    {
        if (actionName.Equals(methodInfo.Name, StringComparison.InvariantCultureIgnoreCase))
            return true;

        if (!actionName.Equals(this.actionName, StringComparison.InvariantCultureIgnoreCase))
            return false;

        var request = controllerContext.RequestContext.HttpContext.Request;
        return request[methodInfo.Name] != null;
    }
}

제어 장치

[Authorize(Roles="CanAddContent")]
public ActionResult CreateContent(Guid contentOwnerId)
{
    var viewModel = new ContentViewModel
    {
        ContentOwnerId = contentOwnerId
        //populate rest of view model
    }
    return View("CreateContent", viewModel);
}

[Authorize(Roles="CanAddContent"), HttpPost, HttpParamAction("CreateContent"), ValidateAntiForgeryToken]
public ActionResult SaveDraft(ContentFormModel model)
{
    //Save as draft
    return RedirectToAction("CreateContent");
}

[Authorize(Roles="CanAddContent"), HttpPost, HttpParamAction("CreateContent"), ValidateAntiForgeryToken]
public ActionResult Publish(ContentFormModel model)
{
    //publish content
    return RedirectToAction("CreateContent");
}

전망

@using (Ajax.BeginForm("CreateContent", "MyController", new { contentOwnerId = Model.ContentOwnerId }))
{
    @Html.AntiForgeryToken()
    @Html.HiddenFor(x => x.ContentOwnerId)

    <!-- Rest of your form controls -->
    <input name="SaveDraft" type="submit" value="SaveDraft" />
    <input name="Publish" type="submit" value="Publish" />
}

HtmlHelperActionButton 메서드를 만들었습니다 . 그것은 지정된 컨트롤러 / 동작에 양식을 제출할 OnClick 이벤트 에서 약간의 자바 스크립트 가있는 일반 입력 버튼을 생성 합니다.

너는 그처럼 도우미를 사용한다.

@Html.ActionButton("MyControllerName", "MyActionName", "button text")

그러면 다음 HTML이 생성됩니다.

<input type="button" value="button text" onclick="this.form.action = '/MyWebsiteFolder/MyControllerName/MyActionName'; this.form.submit();">

다음은 확장 메소드 코드입니다.

VB.Net

<System.Runtime.CompilerServices.Extension()>
Function ActionButton(pHtml As HtmlHelper, pAction As String, pController As String, pRouteValues As Object, pBtnValue As String, pBtnName As String, pBtnID As String) As MvcHtmlString
    Dim urlHelperForActionLink As UrlHelper
    Dim btnTagBuilder As TagBuilder

    Dim actionLink As String
    Dim onClickEventJavascript As String

    urlHelperForActionLink = New UrlHelper(pHtml.ViewContext.RequestContext)
    If pController <> "" Then
        actionLink = urlHelperForActionLink.Action(pAction, pController, pRouteValues)
    Else
        actionLink = urlHelperForActionLink.Action(pAction, pRouteValues)
    End If
    onClickEventJavascript = "this.form.action = '" & actionLink & "'; this.form.submit();"

    btnTagBuilder = New TagBuilder("input")
    btnTagBuilder.MergeAttribute("type", "button")

    btnTagBuilder.MergeAttribute("onClick", onClickEventJavascript)

    If pBtnValue <> "" Then btnTagBuilder.MergeAttribute("value", pBtnValue)
    If pBtnName <> "" Then btnTagBuilder.MergeAttribute("name", pBtnName)
    If pBtnID <> "" Then btnTagBuilder.MergeAttribute("id", pBtnID)

    Return MvcHtmlString.Create(btnTagBuilder.ToString(TagRenderMode.Normal))
End Function

C # (C # 코드는 VB DLL에서 디 컴파일되므로 약간의 미화를 얻을 수 있지만 시간은 너무 짧습니다 :-))

public static MvcHtmlString ActionButton(this HtmlHelper pHtml, string pAction, string pController, object pRouteValues, string pBtnValue, string pBtnName, string pBtnID)
{
    UrlHelper urlHelperForActionLink = new UrlHelper(pHtml.ViewContext.RequestContext);
    bool flag = Operators.CompareString(pController, "", true) != 0;
    string actionLink;
    if (flag)
    {
        actionLink = urlHelperForActionLink.Action(pAction, pController, System.Runtime.CompilerServices.RuntimeHelpers.GetObjectValue(pRouteValues));
    }
    else
    {
        actionLink = urlHelperForActionLink.Action(pAction, System.Runtime.CompilerServices.RuntimeHelpers.GetObjectValue(pRouteValues));
    }
    string onClickEventJavascript = "this.form.action = '" + actionLink + "'; this.form.submit();";
    TagBuilder btnTagBuilder = new TagBuilder("input");
    btnTagBuilder.MergeAttribute("type", "button");
    btnTagBuilder.MergeAttribute("onClick", onClickEventJavascript);
    flag = (Operators.CompareString(pBtnValue, "", true) != 0);
    if (flag)
    {
        btnTagBuilder.MergeAttribute("value", pBtnValue);
    }
    flag = (Operators.CompareString(pBtnName, "", true) != 0);
    if (flag)
    {
        btnTagBuilder.MergeAttribute("name", pBtnName);
    }
    flag = (Operators.CompareString(pBtnID, "", true) != 0);
    if (flag)
    {
        btnTagBuilder.MergeAttribute("id", pBtnID);
    }
    return MvcHtmlString.Create(btnTagBuilder.ToString(TagRenderMode.Normal));
}

이러한 메서드에는 다양한 매개 변수가 있지만 사용하기 쉽도록 필요한 매개 변수 만 사용하는 오버로드를 만들 수 있습니다.


나는 파티에 꽤 늦었지만, 여기 간다 ... @mkozicki에서 구현 한 것은 구현하기 어렵지만 잘못된 코딩 문자열은 필요 없다. 프레임 워크 4.5 이상이 필요합니다 . 기본적으로 컨트롤러 메소드 이름은 라우팅의 핵심이어야합니다.

마크 업 . 버튼 이름은 다음과 같이 입력해야합니다."action:[controllerMethodName]"

( 호출하려는 컨트롤러 메소드의 이름에 대한 유형별 참조를 제공 하는 C # 6 nameof API 사용에 주목하십시오 .

<form>
    ... form fields ....
    <button name="action:@nameof(MyApp.Controllers.MyController.FundDeathStar)" type="submit" formmethod="post">Fund Death Star</button>
    <button name="action:@nameof(MyApp.Controllers.MyController.HireBoba)" type="submit" formmethod="post">Hire Boba Fett</button>
</form>

컨트롤러 :

namespace MyApp.Controllers
{
    class MyController
    {    
        [SubmitActionToThisMethod]
        public async Task<ActionResult> FundDeathStar(ImperialModel model)
        {
            await TrainStormTroopers();
            return View();
        }

        [SubmitActionToThisMethod]
        public async Task<ActionResult> HireBoba(ImperialModel model)
        {
            await RepairSlave1();
            return View();
        }
    }
}

속성 매직 . CallerMemberName선을 사용함을 주목하십시오 .

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class SubmitActionToThisMethodAttribute : ActionNameSelectorAttribute
{        
    public SubmitActionToThisMethodAttribute([CallerMemberName]string ControllerMethodName = "")
    {
        controllerMethod = ControllerMethodName;
        actionFormat = string.Concat(actionConstant, ":", controllerMethod);
    }
    const string actionConstant = "action";
    readonly string actionFormat;
    readonly string controllerMethod;

    public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo)
    {
        var isValidName = false;
        var value = controllerContext.Controller.ValueProvider.GetValue(actionFormat);

        if (value != null)
        {
            controllerContext.Controller.ControllerContext.RouteData.Values[actionConstant] = controllerMethod;
            isValidName = true;
        }
        return isValidName;
    }
}

//model
    public class input_element
        {
         public string Btn { get; set; }
        }   

//views--submit btn can be input type also...
    @using (Html.BeginForm())
    {
            <button type="submit" name="btn" value="verify">
             Verify data</button>
            <button type="submit" name="btn" value="save">
             Save data</button>    
            <button type="submit" name="btn" value="redirect">
                 Redirect</button>
    }

//controller

    public ActionResult About()
        {
            ViewBag.Message = "Your app description page.";
            return View();
        }

        [HttpPost]
        public ActionResult About(input_element model)
        {
                if (model.Btn == "verify")
                {
                // the Verify button was clicked
                }
                else if (model.Btn == "save")
                {
                // the Save button was clicked
                } 
                else if (model.Btn == "redirect")
                {
                // the Redirect button was clicked
                } 
                return View();
        }




form-submit