如何通过 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 中的链接发布的主要内容,如果未能解决你的问题,请参考以下文章

如何在 ASP.NET Core(.NET 6、VS 2022)中禁用浏览器链接

使用 ASP.NET CORE 中的链接从 Cloudinary 下载 pdf 文件

如何将 ASP.NET Core 身份链接到另一个实体?

如何多次提交表单(asp.net core razor)

如何通过 ASP.NET Core 中的 api 控制器更新 IdentityUser 的自定义属性?

如何通过 ASP.NET Core 3 中的中间 Web API 传递未更改的 HTTP 响应?