如何通过 ASP.NET Core 中的链接发布

Posted

技术标签:

【中文标题】如何通过 ASP.NET Core 中的链接发布【英文标题】:How to POST via a link in ASP.NET Core 【发布时间】:2018-02-19 17:01:42 【问题描述】:

我尝试通过链接发布到 SetLanguage 操作,但不确定如何完成以下代码:

<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>                
            <a href="?culture=@culture.Name">@culture.Name</a>
        </div>
    
 </form>

我应该使用form 还是有直接的方法来发送带有culture : 'EN' 参数的POST,例如?

@Url.Action(action: "SetLanguage", controller:"Home", values: new culture = culture.Name , protocol:"POST") 可以工作吗?

我的控制器代码是

[HttpPost]
public IActionResult SetLanguage(string culture, string returnUrl)

    Response.Cookies.Append(
        CookieRequestCultureProvider.DefaultCookieName,
        CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
        new CookieOptions  Expires = DateTimeOffset.UtcNow.AddYears(1) 
    );

    return LocalRedirect(returnUrl);

【问题讨论】:

是的,这肯定会做的工作 【参考方案1】:

我会对链接本身使用操作,我在我的项目中使用这段特定的代码。它就像一个魅力。

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

我的控制器代码如下所示:

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

希望这对您的项目有所帮助!

【讨论】:

奇怪.. 为我工作 您的操作是否具有[HttpPost] 属性? 我的控制器中没有属性 所以,我试过了,它确实有效,感谢您的帮助...但是它不是 POST ;) @NicolasPierre:如果您不将其限制为[HttpPost],那么这并不能解决原始问题。提供标准的GET 操作链接可能是一种更优雅的方式,但它并不能解决问题。【参考方案2】:

链接是 GET 请求。您不能通过链接发布;这就是表格的用途。你需要类似的东西:

<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>

然后,无论您单击哪个按钮,其值都会被发布。如果您希望它看起来像链接,您可以相应地设置按钮的样式。

或者,您可以保留链接,但您需要使用 AJAX 来发布点击。

【讨论】:

它会起作用吗,比如说 3 个按钮都带有 Name 属性? 是的。它本质上就像一个收音机,只有当你点击一个时它会立即提交。 好的...但是,我想成为链接,因为所有 CSS 都设计为链接...有没有办法添加隐藏和点击提交?【参考方案3】:

你可以使用 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>

【讨论】:

这里最好有一个 JavaScript 示例来说明 AJAX 方法。也就是说,有很多更简洁的方法来说明 jQuery 事件处理,如果这里将其视为最佳实践,则可能应该使用这些方法。例如,更常见的方法可能是为参数应用 data-culture 属性,并使用 jQuery 选择器连接事件。【参考方案4】:

您可以创建一个 TagHelper,它将表单生成为 html 并接收您要放置的配置作为参数。 TagHelper 示例: TagHelper 类:

 [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());
    

用法:

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

控制器:

public class DefaultController : Controller

    public IActionResult Index()
    
        return View();
    

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

方法:

public enum Method

    Get,
    Post,
    Delete,
    Put

注册:

@addTagHelper HyperLinkTagHelper.TagHelpers.HyperLinkTagHelper, HyperLinkTagHelper

Example on Github

我没用过,只是来个意见

你可以继承AnchorTagHelper并重写Process方法

【讨论】:

提供一个简单的示例来说明此类标签助手的外观可能很有价值,或者至少提供一篇关于创建类似内容的文章的链接。 @JeremyCaney 我想出了一个例子

以上是关于如何通过 ASP.NET Core 中的链接发布的主要内容,如果未能解决你的问题,请参考以下文章