Mvc Html.ActionButton

Кто-нибудь написал? Я хочу, чтобы он вел себя как ссылка, но выглядел как кнопка. Форма с одной кнопкой не будет делать это, я не хочу POST.

Ответ 1

Самый простой способ сделать это - иметь небольшой тег form с method="get", в который вы помещаете кнопку отправки:

<form method="get" action="/myController/myAction/">
    <input type="submit" value="button text goes here" />
</form>

Конечно, вы можете написать очень простой метод расширения, который принимает текст кнопки и RouteValueDictionary (или анонимный тип с указанием маршрутов) и строит форму, поэтому вам не придется переделывать ее всюду.

EDIT. В ответ на ответ cdmckay, здесь альтернативный код, который использует класс TagBuilder вместо обычного StringBuilder для построения формы, в основном для ясности:

using System.Web.Mvc;
using System.Web.Mvc.Html;
using System.Web.Routing;

namespace MvcApplication1
{
    public static class HtmlExtensions
    {
        public static string ActionButton(this HtmlHelper helper, string value, 
                              string action, string controller, object routeValues)
        {
            var a = (new UrlHelper(helper.ViewContext.RequestContext))
                        .Action(action, controller, routeValues);

            var form = new TagBuilder("form");
            form.Attributes.Add("method", "get");
            form.Attributes.Add("action", a);

            var input = new TagBuilder("input");
            input.Attributes.Add("type", "submit");
            input.Attributes.Add("value", value);

            form.InnerHtml = input.ToString(TagRenderMode.SelfClosing);

            return form.ToString(TagRenderMode.Normal);
        }
    }
}

Кроме того, в отличие от кода cdmckay, этот будет фактически компилироваться;) Я знаю, что в этом коде может быть довольно много накладных расходов, но я ожидаю, что вам не нужно будет запускать много раз на каждой странице. В случае, если вы это сделаете, возможно, есть несколько оптимизаций, которые вы могли бы сделать.

Ответ 2

Если вы хотите, чтобы он вел себя как ссылка, но "выглядите" как кнопка, просто используйте ActionLink с классом CSS.

<%: Html.ActionLink("Back", "Index", null, new { @class = "link-button" })%>

Вот CSS для кнопки, которую я использую.

.link-button {
    -moz-border-radius:0.333em 0.333em 0.333em 0.333em;
    -moz-box-shadow:0 1px 4px rgba(0, 0, 0, 0.4);
    background:-moz-linear-gradient(center top , white, #306AB5 4%, #274976) repeat scroll 0 0 transparent;
    border-color:#306AB5 #2B5892 #274771;
    border-style:solid;
    border-width:1px;
    color:white;
    cursor:pointer;
    display:inline-block;
    font-size:1.167em;
    font-weight:bold;
    line-height:1.429em;
    padding:0.286em 1em 0.357em;
    text-shadow:0 1px 2px rgba(0, 0, 0, 0.4);
}


.link-button {
    color: white;
    border-color: #a1a7ae #909498 #6b7076;
    background: #9fa7b0 url(../images/old-browsers-bg/button-element-grey-bg.png) repeat-x top;
    background: -moz-linear-gradient(
        top,
        white,
        #c5cbce 5%,
        #9fa7b0
    );
    background: -webkit-gradient(
        linear,
        left top, left bottom,
        from(white),
        to(#9fa7b0),
        color-stop(0.05, #c5cbce)
    );
    -moz-text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
    -webkit-text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
    -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);
    -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);
    }
    .link-button:hover {
        border-color: #a1a7b0 #939798 #6e7275;
        background: #b1b5ba url(../images/old-browsers-bg/button-element-grey-hover-bg.png) repeat-x top;
        background: -moz-linear-gradient(
            top,
            white,
            #d6dadc 4%,
            #b1b5ba
        );
        background: -webkit-gradient(
            linear,
            left top, left bottom,
            from(white),
            to(#b1b5ba),
            color-stop(0.03, #d6dadc)
        );
    }
    .link-button:active {
        border-color: #666666 #ffffff #ffffff #979898;
        background: #dddddd url(../images/old-browsers-bg/button-element-grey-active-bg.png) repeat-x top;
        background: -moz-linear-gradient(
            top,
            #f1f1f1,
            #dddddd
        );
        background: -webkit-gradient(
            linear,
            left top, left bottom,
            from(#f1f1f1),
            to(#dddddd)
        );
    }

Ответ 3

Две версии для расширения для...

<button 
    onclick="javascript:window.location=('@Url.Action("Review", "Order", null)')"
    >Review Order</button>

Ненавязчивая версия:

<button data-action="@Url.Action("Review", "Order", null)">Review Order</button>

$(document).on('click', "[data-action]", 
    function(e) { window.location = $(this).attr('data-action'); }
);

Если у вас есть пользователи, у которых не включен javascript, тогда тег формы - путь. Хотя, это делает ситуацию сложной, если ваша ссылка уже находится в форме. Однако вы можете изменить действие и метод на GET.

Ответ 4

Код для ответа Томаса:

public static class HtmlExtensions
{
  public static string ActionButton(this HtmlHelper helper, string value, 
      string action, string controller, object routeValues)
  {
    UrlHelper urlHelper = new UrlHelper(helper.ViewContext);
    var action = urlHelper.Action(action, controller, routeValues);

    var html = new StringBuilder();
    html.AppendFormat("<form method='get' action'{0}'>", action).AppendLine()
        .AppendFormat("    <input type='submit' value='{0}' />", value).AppendLine()
        .AppendFormat("</form>").AppendLine();

    return html.ToString();
  }
}

Ответ 5

Я изменил код Tomas Lyckens, чтобы вернуть MvcHtmlString вместо строки. Это гарантирует, что вывод будет HTML, а не экранирован как текст. Я также xml-документировал это красиво. Благодаря Томасу, который сделал всю настоящую работу.

    /// <summary>
    /// Returns an HTML submit button (enclosed in its own form) that contains the virtual path of the specified action.
    /// </summary>
    /// <param name="helper">The HTML helper instance that this method extends.</param>
    /// <param name="buttonText">The visible text of the button.</param>
    /// <param name="action">The name of the action.</param>
    /// <param name="controller">The name of the controller.</param>
    /// <param name="routeValues">An object that contains the parameters for a route. The parameters are retrieved through reflection by examining the properties of the object. The object is typically created by using object initializer syntax.</param>
    /// <returns></returns>
    public static MvcHtmlString ActionButton(this HtmlHelper helper, string buttonText, string action, string controller, object routeValues)
    {
        string a = (new UrlHelper(helper.ViewContext.RequestContext)).Action(action, controller, routeValues);

        var form = new TagBuilder("form");
        form.Attributes.Add("method", "get");
        form.Attributes.Add("action", a);

        var input = new TagBuilder("input");
        input.Attributes.Add("type", "submit");
        input.Attributes.Add("value", buttonText);

        form.InnerHtml = input.ToString(TagRenderMode.SelfClosing);

        return MvcHtmlString.Create(form.ToString(TagRenderMode.Normal));
    } 

Ответ 6

Вот версия VB.NET с одной дополнительной вещью, параметры контроллера и маршрутов являются необязательными, поэтому их можно использовать без повторения имени контроллера, если он совпадает с текущим/стандартным контроллером для страницы.

Public Module MvcExtensions

    ''' <summary> 
    ''' Returns an HTML submit button (enclosed in its own form) that contains the virtual path of the specified action. 
    ''' </summary> 
    ''' <param name="helper">The HTML helper instance that this method extends.</param> 
    ''' <param name="text">Text displayed in the button.</param> 
    ''' <param name="action">Action name.</param> 
    ''' <param name="controller">Optional controller name, using current when null.</param> 
    ''' <param name="routeValues">
    ''' An object that contains the parameters for a route. The parameters are retrieved
    ''' through reflection by examining the properties of the object.
    ''' The object is typically created by using object initializer syntax.
    ''' </param> 
    ''' <returns>
    ''' HTML output.
    ''' </returns> 
    <Extension()> _
    Public Function ActionButton(helper As HtmlHelper, text As String, action As String,
                                 Optional controller As String = Nothing, Optional routeValues As Object = Nothing) As MvcHtmlString

        ' Validate parameters
        If String.IsNullOrEmpty(text) Then Throw New ArgumentNullException("text")

        ' Get post back URL for action
        Dim actionUrl As String = New UrlHelper(helper.ViewContext.RequestContext).Action(action, controller, routeValues)

        ' Build form tag with action URL
        Dim form = New TagBuilder("form")
        form.Attributes.Add("method", "get")
        form.Attributes.Add("action", actionUrl)

        ' Add button
        Dim input = New TagBuilder("input")
        input.Attributes.Add("type", "submit")
        input.Attributes.Add("value", text)
        form.InnerHtml = input.ToString(TagRenderMode.SelfClosing)

        ' Return result as HTML
        Return MvcHtmlString.Create(form.ToString(TagRenderMode.Normal))

    End Function

End Module

Затем он может быть вызван, как и другие другие элементы управления MVC, с минимальным кодом на странице.

Это должно было с самого начала перейти в основную структуру MVC; это кажется очевидным требованием. Я думаю, что кнопки намного интуитивны для пользователя при выполнении действий, которые создают или изменяют вещи, а не ссылки. Ссылки должны просто перейти к соответствующей информации (ничего не менять). Если бы у меня была сетка, я бы использовал ActionLink для любой навигации по данным (например, нажмите имя продукта на страницу продукта goto), но только ActionButton для реальных "действий", таких как редактирование и удаление.

Ответ 7

Если вам нужна кнопка, которая работает как ссылка, это должно работать:

<input type="button" value="Button Text"
  onclick="@("location.href='http://stackoverflow.com/q/901372/2460971'")" />

Если вы хотите, чтобы кнопка использовала действие контроллера, требуется только небольшое изменение:

<input type="button" value="Button Text"
  onclick="@("location.href='" + Url.Action("ActionName", "ControllerName") + "'")" />