tags:

views:

649

answers:

3

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.

+3  A: 

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.

Tomas Lycken
Other than not having the using statements, what is stopping my example from compiling? (I haven't tested it, I'm just curious)
cdmckay
Well, for one thing, the Url.Action() method isn't available except for in the view, because Url is a property of the ViewPage/ViewUserControl, that maps to an instance of a UrlHelper. Instead of just referencing a property that doesn't exist, i create an instance based on the current RequestContext. I see now that you have changed your code to "var action = Html.ActionLink(...)", which would compile if you used "var action = helper.ActionLink(...)", but it would give you the entire <a> tag, which you don't want in the action property of the form...
Tomas Lycken
+1  A: 

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();
  }
}
cdmckay
In response to your edit: you can't use Html.ActionLink() - use helper.ActionLink if you want that. However, that will produce an entire anchor tag (and currently with an incorrect url, seeing as the first parameter is the link text and the second is the action name...) and that is not what we want here.
Tomas Lycken
Whoops, I had Url.Action() before, then I second guessed myself. Anyway, there ya go.
cdmckay
Also replace Url with urlHelper.
cdmckay
+1  A: 

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: #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)
        );
    }
Brett