5
5
using System . Collections . Generic ;
6
6
using System . Linq ;
7
7
using Microsoft . AspNet . Mvc . Rendering ;
8
+ using Microsoft . AspNet . Mvc . TagHelpers . Internal ;
8
9
using Microsoft . AspNet . Razor . Runtime . TagHelpers ;
9
10
using Microsoft . AspNet . Razor . TagHelpers ;
10
11
@@ -16,11 +17,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
16
17
[ ContentBehavior ( ContentBehavior . Append ) ]
17
18
public class FormTagHelper : TagHelper
18
19
{
19
- [ Activate ]
20
- private ViewContext ViewContext { get ; set ; }
20
+ private const string RouteAttributePrefix = "route-" ;
21
21
22
22
[ Activate ]
23
- private AntiForgery AntiForgery { get ; set ; }
23
+ private ViewContext ViewContext { get ; set ; }
24
24
25
25
[ Activate ]
26
26
private IHtmlGenerator Generator { get ; set ; }
@@ -54,72 +54,68 @@ public override void Process(TagHelperContext context, TagHelperOutput output)
54
54
}
55
55
else
56
56
{
57
- // TODO: Make this behavior optional once https://github.com/aspnet/Razor/issues/121 is completed.
58
- output . Content = AntiForgery . GetHtml ( ViewContext . HttpContext ) . ToString ( ) ;
59
-
60
57
var routeValues = PullRouteValues ( output . Attributes ) ;
61
58
var tagBuilder = Generator . GenerateForm ( ViewContext ,
62
59
Action ,
63
60
Controller ,
64
61
routeValues ,
65
62
Method ,
66
- htmlAttributes : new Dictionary < string , object > ( ) ) ;
63
+ htmlAttributes : null ) ;
64
+
65
+ TagHelperOutputHelper . Merge ( tagBuilder , output ) ;
67
66
68
- TagHelperOutputHelper . MergeAttributes ( output , tagBuilder ) ;
67
+ // TODO: Make this behavior optional once https://github.com/aspnet/Razor/issues/121 is completed.
68
+ var antiForgeryTag = Generator . GenerateAntiForgery ( ViewContext ) ;
69
+ output . Content += antiForgeryTag . ToString ( TagRenderMode . SelfClosing ) ;
69
70
}
70
71
}
71
72
72
73
// TODO: We will not need this method once https://github.com/aspnet/Razor/issues/89 is completed.
73
74
private static Dictionary < string , object > PullRouteValues ( IDictionary < string , string > htmlAttributes )
74
75
{
75
- var routeAttributePrefix = "route-" ;
76
-
77
76
// We're only interested in HTML attributes that have the desired routeAttributePrefix.
78
77
var routeAttributes = htmlAttributes . Where ( attribute =>
79
- attribute . Key . StartsWith ( routeAttributePrefix , StringComparison . OrdinalIgnoreCase ) ) ;
78
+ attribute . Key . StartsWith ( RouteAttributePrefix , StringComparison . OrdinalIgnoreCase ) ) ;
80
79
81
- // We need to remove any route based HTML attributes from the HTML attributes dictionary because
82
- // they shouldn't be treated as HTML attributes, they're route values.
80
+ // Route based HTML attributes shouldn't be treated as HTML attributes, they're only route values.
83
81
foreach ( var attribute in routeAttributes )
84
82
{
85
83
htmlAttributes . Remove ( attribute . Key ) ;
86
84
}
87
85
88
- // We build a Dictionary<string, object> because Generator.GenerateForm does not accept a
89
- // Dictionary <string, string>.
90
- return routeAttributes . ToDictionary ( attribute => attribute . Key . Substring ( routeAttributePrefix . Length ) ,
86
+ // Generator.GenerateForm does not accept a Dictionary<string, string> for routeValues.
87
+ return routeAttributes . ToDictionary ( attribute => attribute . Key . Substring ( RouteAttributePrefix . Length ) ,
91
88
attribute => ( object ) attribute . Value ) ;
92
89
}
93
90
94
91
private void RestoreBoundHtmlAttributes ( TagHelperContext context , TagHelperOutput output )
95
92
{
96
- var attributesToRestore = new List < string > ( ) ;
97
-
98
93
if ( Action != null )
99
94
{
100
- attributesToRestore . Add ( nameof ( Action ) ) ;
95
+ RestoreBoundHtmlAttribute ( nameof ( Action ) , context , output ) ;
101
96
}
102
97
103
98
if ( Controller != null )
104
99
{
105
- attributesToRestore . Add ( nameof ( Controller ) ) ;
100
+ RestoreBoundHtmlAttribute ( nameof ( Controller ) , context , output ) ;
106
101
}
107
102
108
103
if ( Method != null )
109
104
{
110
- attributesToRestore . Add ( nameof ( Method ) ) ;
105
+ RestoreBoundHtmlAttribute ( nameof ( Method ) , context , output ) ;
111
106
}
107
+ }
112
108
113
- foreach ( var attributeName in attributesToRestore )
114
- {
115
- // We need to look for the KeyValuePair<string, object> attribute so we can ensure that the attribute
116
- // that we re-add to the output object has the same attribute name as the one the user typed.
117
- var entry = context . AllAttributes . Single ( attribute =>
118
- attribute . Key . Equals ( attributeName , StringComparison . OrdinalIgnoreCase ) ) ;
119
- var originalAttribute = new KeyValuePair < string , string > ( entry . Key , entry . Value . ToString ( ) ) ;
109
+ private static void RestoreBoundHtmlAttribute ( string boundAttributeName ,
110
+ TagHelperContext context ,
111
+ TagHelperOutput output )
112
+ {
113
+ // We look for the original attribute so we can then retrieve the exact attribute name the user typed.
114
+ var entry = context . AllAttributes . Single ( attribute =>
115
+ attribute . Key . Equals ( boundAttributeName , StringComparison . OrdinalIgnoreCase ) ) ;
116
+ var originalAttribute = new KeyValuePair < string , string > ( entry . Key , entry . Value . ToString ( ) ) ;
120
117
121
- output . Attributes . Add ( originalAttribute ) ;
122
- }
118
+ output . Attributes . Add ( originalAttribute ) ;
123
119
}
124
120
}
125
121
}
0 commit comments