Has anyone written one? I want it to behave like a link but look like a button. A form with a single button wont do it has I don\'t want any POST.
If you want it to behave like a link but "look" like a button just use the ActionLink with a CSS Class.
<%: Html.ActionLink("Back", "Index", null, new { @class = "link-button" })%>
Here is the CSS for a Button that I am using.
.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: #ffffdffffd url(../images/old-browsers-bg/button-element-grey-active-bg.png) repeat-x top;
background: -moz-linear-gradient(
top,
#f1f1f1,
#ffffdffffd
);
background: -webkit-gradient(
linear,
left top, left bottom,
from(#f1f1f1),
to(#ffffdffffd)
);
}
Two versions to make an extension for...
<button
onclick="javascript:window.location=('@Url.Action("Review", "Order", null)')"
>Review Order</button>
Unobtrusive version:
<button data-action="@Url.Action("Review", "Order", null)">Review Order</button>
$(document).on('click', "[data-action]",
function(e) { window.location = $(this).attr('data-action'); }
);
If you have users which do not have javascript turned on, then form tag is the way to go. Although, this make the situation difficult if your link is already within a form. However, you could change the action and method to GET.
The easiest way to do it is to have a small form
tag with method="get"
, in which you place a submit button:
<form method="get" action="/myController/myAction/">
<input type="submit" value="button text goes here" />
</form>
You can of course write a very simple extension method that takes the button text and a RouteValueDictionary
(or an anonymous type with the routevalues) and builds the form so you won't have to re-do it everywhere.
EDIT: In response to cdmckay's answer, here's an alternative code that uses the TagBuilder
class instead of a regular StringBuilder
to build the form, mostly for clarity:
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);
}
}
}
Also, as opposed to cdmckay's code, this one will actually compile ;) I am aware that there might be quite a lot of overhead in this code, but I am expecting that you won't need to run it a lot of times on each page. In case you do, there is probably a bunch of optimizations that you could do.
If you want a button that functions like a link this should work:
<input type="button" value="Button Text"
onclick="@("location.href='http://stackoverflow.com/q/901372/2460971'")" />
If you want the button to use a controller action only a minor change is needed:
<input type="button" value="Button Text"
onclick="@("location.href='" + Url.Action("ActionName", "ControllerName") + "'")" />
I modified Tomas Lyckens code to return a MvcHtmlString instead of just a string. This makes sure the output is HTML, not escaped as text. I also xml-documented it nicely. Thanks to Tomas who did all the real work.
/// <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));
}
Code for Tomas' answer:
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();
}
}