How to POST via a link in ASP.NET Core

I would use action on the links itself, I use this particular piece of code in my project. And it works like a charm.

<a asp-controller="YourController"
 asp-action="SetLanguage"
 asp-route-culture="@culture.Name"
 asp-route-returnUri="@Context.Request.Path">
</a>

My Controller code look like this then:

  public IActionResult SetLanguage(string culture, string returnUri = "")
        {
            SetSettings(newCultureName);
            return Redirect(returnUri);
        }

Hope this helps you in your project !


You can create a TagHelper that generates form as html and receives as parameters the configurations you want to put. Example with TagHelper: TagHelper class:

 [HtmlTargetElement("HyperLink")]
public class HyperLinkTagHelper : TagHelper
{
    #region Proprietes
    public string AspAction { get; set; }
    public string AspController { get; set; }
    public Method Method { get; set; } = Method.Get;
    public string Class { get; set; }
    public string Style { get; set; }

    private IDictionary<string, string> _routeValues;

    [HtmlAttributeName("asp-all-route-data", DictionaryAttributePrefix = "asp-route-")]
    public IDictionary<string, string> RouteValues
    {
        get => _routeValues ??= new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
        set => _routeValues = value;
    }
    #endregion


    #region Injectable

    private readonly IUrlHelper _urlHelper;
    #endregion

    /// <summary>
    /// Constructor
    /// </summary>
    /// <param name="urlHelper"></param>
    public HyperLinkTagHelper(IUrlHelper urlHelper)
    {
        _urlHelper = urlHelper;
    }

    /// <summary>
    /// Render output 
    /// </summary>
    /// <param name="context"></param>
    /// <param name="output"></param>
    /// <returns></returns>
    public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
    {
        output.TagMode = TagMode.StartTagAndEndTag;
        var linkName = (await output.GetChildContentAsync()).GetContent();
        var builder = new StringBuilder();
        var method = Method.ToString().ToLower();
        var link = _urlHelper.Action(AspAction, AspController);
        builder.AppendFormat("<form method='{0}' role='form' action='{1}'>", method, link);
        foreach (var (key, value) in _routeValues)
        {
            builder.AppendFormat("<input type='hidden' name='{0}' value='{1}'>", key, value);
        }
        builder.AppendFormat("<input type='submit' value='{0}' class='{1}' style='{2}'/>", linkName, Class, Style);
        builder.Append("</form>");
        output.Content.SetHtmlContent(builder.ToString());
    }
}

Usage:

<HyperLink asp-action="SendData" asp-controller="Default" method="Post" asp-route-data="test">Send data</HyperLink>

Controller:

public class DefaultController : Controller
{
    public IActionResult Index()
    {
        return View();
    }

    [HttpPost]
    public IActionResult SendData(string data)
    {
        Console.WriteLine(data);
        return RedirectToAction("Index");
    }
}

Method:

public enum Method
{
    Get,
    Post,
    Delete,
    Put
}

Registration:

@addTagHelper HyperLinkTagHelper.TagHelpers.HyperLinkTagHelper, HyperLinkTagHelper

Example on Github

I did not use it, I came only with an opinion

You can inherit from AnchorTagHelper and rewrite the Process method


You can use JQuery :

@foreach (var culture in cultures)
{
    <div>
        <a href="javascript:setLanguage('@culture.Name')">@culture.Name</a>
    </div>
}

<script type="text/javascript">

    function setLanguage(culture)
    { 
        $.post("/home/setlanguage", { culture: culture})
            .done(function (data) {
                location.reload();
            });
    }
</script>

Links are GET requests. You cannot post via a link; that is what forms are for. You'd need something like:

<form id="selectLanguage" asp-controller="Home" asp-action="SetLanguage" asp-route-returnUrl="@Context.Request.Path" method="post" role="form">
    @foreach (var culture in cultures) {
        <div>                
            <button type="submit" name="culture" value="@culture.Name">
                @culture.Name
            </button>
        </div>
    }
</form>

Then, whichever button you click, its value will be posted. If you want it to look like links, you can style the buttons accordingly.

Alternatively, you can keep the links, but you would need to use AJAX to post on click.