从AnchorTagHelper中的asp-all-route-data覆盖RouteValues

时间:2019-06-13 07:19:47

标签: c# asp.net-mvc asp.net-core

将TagHelpers与MVC Core(2.1)一起使用时,可以定义asp-all-route-data和其他asp-route-x。但是,如果x包含在传递给all-route-data的对象内,则会引发异常:

An element with the key 'x' already exists in the RouteValueDictionary

是否可以更改此行为(扩展TagHelper,自定义TagHelper等)以在这种情况下仅更新值,而不是尝试创建新条目。

所以这个:

if(RouteValueDictionary.HasKey(x)) 
   RouteValueDictionary[x] = value;

代替(可能是这样):

RouteValueDictionary.Add(x, value);

(基本上,我的代码中的if甚至在这样的分配中都不需要)

编辑(也许可以解释用例):存在一个对象,其中包含表单的所有查询参数,但也有一些链接基本上应该发送相同的数据并更改值。仅当对每个链接使用带有onclick的javascript,设置隐藏的输入并提交表单时,才能提交表单。但我宁愿不使用JS,因为“中键单击到新选项卡”之类的功能将丢失。

1 个答案:

答案 0 :(得分:0)

Tseng的答案非常有用,但是,如果有必要使用对象作为值而不是上下文,则可能效果不佳。

最后,我们创建了一个TagHelper,它仅创建查询参数:

[HtmlTargetElement("a", Attributes = RouteValuesDictionaryName)]
[HtmlTargetElement("a", Attributes = RouteValuesPrefix + "*")]
public class SearchLinkTagHelper : TagHelper
{
    private const string RouteValuesDictionaryName = "my-all-route-data";
    private const string RouteValuesPrefix = "my-route-";
    private const string Href = "href";

    private IDictionary<string, string> _routeValues;

    public override int Order => 1;

    [HtmlAttributeName(RouteValuesDictionaryName, DictionaryAttributePrefix = RouteValuesPrefix)]
    public IDictionary<string, string> RouteValues
    {
        get => _routeValues ?? (_routeValues = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase));
        set => _routeValues = value;
    }

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        output.Attributes.TryGetAttribute(Href, out var href);

        var fixedRouteValues = new Dictionary<string, string>();
        foreach (var (newKey, value) in _routeValues.Where(r=>!string.IsNullOrWhiteSpace(r.Value)))
        {
            var key = fixedRouteValues.Keys.FirstOrDefault(k => string.Equals(k, newKey, StringComparison.InvariantCultureIgnoreCase)) ?? newKey;
            fixedRouteValues[key] = value;
        }

        var query = string.Join("&", fixedRouteValues.Select(kvp => $"{kvp.Key}={kvp.Value}"));
        var hrefValue = href.Value;
        output.Attributes.Remove(href);
        href = new TagHelperAttribute(Href, hrefValue + "?" +query);
        output.Attributes.Add(href);

    }
}