@@ -13,54 +13,157 @@ namespace InertiaCore;
13
13
public class Response : IActionResult
14
14
{
15
15
private readonly string _component ;
16
- private readonly object _props ;
16
+ private readonly Dictionary < string , object ? > _props ;
17
17
private readonly string _rootView ;
18
18
private readonly string ? _version ;
19
19
20
20
private ActionContext ? _context ;
21
21
private Page ? _page ;
22
22
private IDictionary < string , object > ? _viewData ;
23
23
24
- public Response ( string component , object props , string rootView , string ? version )
24
+ internal Response ( string component , Dictionary < string , object ? > props , string rootView , string ? version )
25
25
=> ( _component , _props , _rootView , _version ) = ( component , props , rootView , version ) ;
26
26
27
27
public async Task ExecuteResultAsync ( ActionContext context )
28
28
{
29
29
SetContext ( context ) ;
30
30
await ProcessResponse ( ) ;
31
-
32
31
await GetResult ( ) . ExecuteResultAsync ( _context ! ) ;
33
32
}
34
33
35
34
protected internal async Task ProcessResponse ( )
36
35
{
36
+ var props = await ResolveProperties ( ) ;
37
+
37
38
var page = new Page
38
39
{
39
40
Component = _component ,
40
41
Version = _version ,
41
42
Url = _context ! . RequestedUri ( ) ,
42
- Props = await ResolveProperties ( _props . GetType ( ) . GetProperties ( )
43
- . ToDictionary ( o => o . Name . ToCamelCase ( ) , o => o . GetValue ( _props ) ) )
43
+ Props = props
44
44
} ;
45
45
46
- var shared = _context ! . HttpContext . Features . Get < InertiaSharedData > ( ) ;
47
- if ( shared != null )
48
- page . Props = shared . GetMerged ( page . Props ) ;
49
-
50
46
page . Props [ "errors" ] = GetErrors ( ) ;
51
47
52
48
SetPage ( page ) ;
53
49
}
54
50
55
- private static async Task < Dictionary < string , object ? > > PrepareProps ( Dictionary < string , object ? > props )
51
+ /// <summary>
52
+ /// Resolve the properties for the response.
53
+ /// </summary>
54
+ private async Task < Dictionary < string , object ? > > ResolveProperties ( )
55
+ {
56
+ var props = _props ;
57
+
58
+ props = ResolveSharedProps ( props ) ;
59
+ props = ResolvePartialProperties ( props ) ;
60
+ props = ResolveAlways ( props ) ;
61
+ props = await ResolvePropertyInstances ( props ) ;
62
+
63
+ return props ;
64
+ }
65
+
66
+ /// <summary>
67
+ /// Resolve `shared` props stored in the current request context.
68
+ /// </summary>
69
+ private Dictionary < string , object ? > ResolveSharedProps ( Dictionary < string , object ? > props )
70
+ {
71
+ var shared = _context ! . HttpContext . Features . Get < InertiaSharedProps > ( ) ;
72
+ if ( shared != null )
73
+ props = shared . GetMerged ( props ) ;
74
+
75
+ return props ;
76
+ }
77
+
78
+ /// <summary>
79
+ /// Resolve the `only` and `except` partial request props.
80
+ /// </summary>
81
+ private Dictionary < string , object ? > ResolvePartialProperties ( Dictionary < string , object ? > props )
82
+ {
83
+ var isPartial = _context ! . IsInertiaPartialComponent ( _component ) ;
84
+
85
+ if ( ! isPartial )
86
+ return props
87
+ . Where ( kv => kv . Value is not LazyProp )
88
+ . ToDictionary ( kv => kv . Key , kv => kv . Value ) ;
89
+
90
+ props = props . ToDictionary ( kv => kv . Key , kv => kv . Value ) ;
91
+
92
+ if ( _context ! . HttpContext . Request . Headers . ContainsKey ( InertiaHeader . PartialOnly ) )
93
+ props = ResolveOnly ( props ) ;
94
+
95
+ if ( _context ! . HttpContext . Request . Headers . ContainsKey ( InertiaHeader . PartialExcept ) )
96
+ props = ResolveExcept ( props ) ;
97
+
98
+ return props ;
99
+ }
100
+
101
+ /// <summary>
102
+ /// Resolve the `only` partial request props.
103
+ /// </summary>
104
+ private Dictionary < string , object ? > ResolveOnly ( Dictionary < string , object ? > props )
105
+ {
106
+ var onlyKeys = _context ! . HttpContext . Request . Headers [ InertiaHeader . PartialOnly ]
107
+ . ToString ( ) . Split ( ',' )
108
+ . Select ( k => k . Trim ( ) )
109
+ . Where ( k => ! string . IsNullOrEmpty ( k ) )
110
+ . ToList ( ) ;
111
+
112
+ return props . Where ( kv => onlyKeys . Contains ( kv . Key , StringComparer . OrdinalIgnoreCase ) )
113
+ . ToDictionary ( kv => kv . Key , kv => kv . Value ) ;
114
+ }
115
+
116
+ /// <summary>
117
+ /// Resolve the `except` partial request props.
118
+ /// </summary>
119
+ private Dictionary < string , object ? > ResolveExcept ( Dictionary < string , object ? > props )
120
+ {
121
+ var exceptKeys = _context ! . HttpContext . Request . Headers [ InertiaHeader . PartialExcept ]
122
+ . ToString ( ) . Split ( ',' )
123
+ . Select ( k => k . Trim ( ) )
124
+ . Where ( k => ! string . IsNullOrEmpty ( k ) )
125
+ . ToList ( ) ;
126
+
127
+ return props . Where ( kv => exceptKeys . Contains ( kv . Key , StringComparer . OrdinalIgnoreCase ) == false )
128
+ . ToDictionary ( kv => kv . Key , kv => kv . Value ) ;
129
+ }
130
+
131
+ /// <summary>
132
+ /// Resolve `always` properties that should always be included on all visits, regardless of "only" or "except" requests.
133
+ /// </summary>
134
+ private Dictionary < string , object ? > ResolveAlways ( Dictionary < string , object ? > props )
135
+ {
136
+ var alwaysProps = _props . Where ( o => o . Value is AlwaysProp ) ;
137
+
138
+ return props
139
+ . Where ( kv => kv . Value is not AlwaysProp )
140
+ . Concat ( alwaysProps ) . ToDictionary ( kv => kv . Key , kv => kv . Value ) ;
141
+ }
142
+
143
+ /// <summary>
144
+ /// Resolve all necessary class instances in the given props.
145
+ /// </summary>
146
+ private static async Task < Dictionary < string , object ? > > ResolvePropertyInstances ( Dictionary < string , object ? > props )
56
147
{
57
- return ( await Task . WhenAll ( props . Select ( async pair => pair . Value switch
148
+ return ( await Task . WhenAll ( props . Select ( async pair =>
58
149
{
59
- Func < object ? > f => ( pair . Key , f . Invoke ( ) ) ,
60
- LazyProp l => ( pair . Key , await l . Invoke ( ) ) ,
61
- AlwaysProp l => ( pair . Key , await l . Invoke ( ) ) ,
62
- _ => ( pair . Key , pair . Value )
63
- } ) ) ) . ToDictionary ( pair => pair . Key , pair => pair . Item2 ) ;
150
+ var key = pair . Key . ToCamelCase ( ) ;
151
+
152
+ var value = pair . Value switch
153
+ {
154
+ Func < object ? > f => ( key , await f . ResolveAsync ( ) ) ,
155
+ Task t => ( key , await t . ResolveResult ( ) ) ,
156
+ InvokableProp p => ( key , await p . Invoke ( ) ) ,
157
+ _ => ( key , pair . Value )
158
+ } ;
159
+
160
+ if ( value . Item2 is Dictionary < string , object ? > dict )
161
+ {
162
+ value = ( key , await ResolvePropertyInstances ( dict ) ) ;
163
+ }
164
+
165
+ return value ;
166
+ } ) ) ) . ToDictionary ( pair => pair . key , pair => pair . Item2 ) ;
64
167
}
65
168
66
169
protected internal JsonResult GetJson ( )
@@ -93,7 +196,7 @@ private ViewResult GetView()
93
196
94
197
protected internal IActionResult GetResult ( ) => _context ! . IsInertiaRequest ( ) ? GetJson ( ) : GetView ( ) ;
95
198
96
- private IDictionary < string , string > GetErrors ( )
199
+ private Dictionary < string , string > GetErrors ( )
97
200
{
98
201
if ( ! _context ! . ModelState . IsValid )
99
202
return _context ! . ModelState . ToDictionary ( o => o . Key . ToCamelCase ( ) ,
@@ -111,48 +214,4 @@ public Response WithViewData(IDictionary<string, object> viewData)
111
214
_viewData = viewData ;
112
215
return this ;
113
216
}
114
-
115
- private async Task < Dictionary < string , object ? > > ResolveProperties ( Dictionary < string , object ? > props )
116
- {
117
- var isPartial = _context ! . IsInertiaPartialComponent ( _component ) ;
118
-
119
- if ( ! isPartial )
120
- {
121
- props = props
122
- . Where ( kv => kv . Value is not LazyProp )
123
- . ToDictionary ( kv => kv . Key , kv => kv . Value ) ;
124
- }
125
- else
126
- {
127
- props = props . ToDictionary ( kv => kv . Key , kv => kv . Value ) ;
128
-
129
- if ( _context ! . HttpContext . Request . Headers . ContainsKey ( InertiaHeader . PartialOnly ) )
130
- props = ResolveOnly ( props ) ;
131
-
132
- if ( _context ! . HttpContext . Request . Headers . ContainsKey ( InertiaHeader . PartialExcept ) )
133
- props = ResolveExcept ( props ) ;
134
- }
135
-
136
- props = ResolveAlways ( props ) ;
137
- props = await PrepareProps ( props ) ;
138
-
139
- return props ;
140
- }
141
-
142
- private Dictionary < string , object ? > ResolveOnly ( Dictionary < string , object ? > props )
143
- => _context ! . OnlyProps ( props ) ;
144
-
145
- private Dictionary < string , object ? > ResolveExcept ( Dictionary < string , object ? > props )
146
- => _context ! . ExceptProps ( props ) ;
147
-
148
- private Dictionary < string , object ? > ResolveAlways ( Dictionary < string , object ? > props )
149
- {
150
- var alwaysProps = _props . GetType ( ) . GetProperties ( )
151
- . Where ( o => o . PropertyType == typeof ( AlwaysProp ) )
152
- . ToDictionary ( o => o . Name . ToCamelCase ( ) , o => o . GetValue ( _props ) ) ;
153
-
154
- return props
155
- . Where ( kv => kv . Value is not AlwaysProp )
156
- . Concat ( alwaysProps ) . ToDictionary ( kv => kv . Key , kv => kv . Value ) ;
157
- }
158
217
}
0 commit comments