将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,因为“中键单击到新选项卡”之类的功能将丢失。
答案 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);
}
}