@@ -117,11 +117,8 @@ public IDotvvmPresenter GetDefaultPresenter(IServiceProvider provider)
117117 /// <param name="virtualPath">The virtual path of the Dothtml file.</param>
118118 /// <param name="defaultValues">The default values.</param>
119119 /// <param name="presenterFactory">Delegate creating the presenter handling this route</param>
120- public void Add ( string routeName , string ? url , string virtualPath , object ? defaultValues = null , Func < IServiceProvider , IDotvvmPresenter > ? presenterFactory = null , LocalizedRouteUrl [ ] ? localizedUrls = null )
120+ public void Add ( string routeName , string url , string ? virtualPath , object ? defaultValues = null , Func < IServiceProvider , IDotvvmPresenter > ? presenterFactory = null , LocalizedRouteUrl [ ] ? localizedUrls = null )
121121 {
122- ThrowIfFrozen ( ) ;
123-
124- virtualPath = CombinePath ( group ? . VirtualPathPrefix , virtualPath ) ;
125122 AddCore ( routeName , url , virtualPath , defaultValues , presenterFactory , localizedUrls ) ;
126123 }
127124
@@ -132,26 +129,74 @@ public void Add(string routeName, string? url, string virtualPath, object? defau
132129 /// <param name="url">The URL.</param>
133130 /// <param name="defaultValues">The default values.</param>
134131 /// <param name="presenterFactory">The presenter factory.</param>
135- public void Add ( string routeName , string ? url , Func < IServiceProvider , IDotvvmPresenter > ? presenterFactory = null , object ? defaultValues = null , LocalizedRouteUrl [ ] ? localizedUrls = null )
132+ public void Add ( string routeName , string url , Func < IServiceProvider , IDotvvmPresenter > presenterFactory , object ? defaultValues = null , LocalizedRouteUrl [ ] ? localizedUrls = null )
133+ {
134+ AddCore ( routeName , url , virtualPath : null , defaultValues , presenterFactory , localizedUrls ) ;
135+ }
136+
137+ /// <summary>
138+ /// Adds the specified route name.
139+ /// </summary>
140+ /// <param name="routeName">Name of the route.</param>
141+ /// <param name="url">The URL.</param>
142+ /// <param name="presenterType">The presenter factory.</param>
143+ /// <param name="defaultValues">The default values.</param>
144+ public void Add ( string routeName , string url , Type presenterType , object ? defaultValues = null , LocalizedRouteUrl [ ] ? localizedUrls = null )
145+ {
146+ if ( ! typeof ( IDotvvmPresenter ) . IsAssignableFrom ( presenterType ) )
147+ {
148+ throw new ArgumentException ( $@ "{ nameof ( presenterType ) } has to inherit from DotVVM.Framework.Hosting.IDotvvmPresenter.", nameof ( presenterType ) ) ;
149+ }
150+ Func < IServiceProvider , IDotvvmPresenter > presenterFactory = provider => ( IDotvvmPresenter ) provider . GetRequiredService ( presenterType ) ;
151+ AddCore ( routeName , url , virtualPath : null , defaultValues , presenterFactory , localizedUrls ) ;
152+ }
153+
154+ /// <summary>
155+ /// Adds the specified name.
156+ /// </summary>
157+ public void Add ( RouteBase route )
136158 {
137159 ThrowIfFrozen ( ) ;
160+ if ( dictionary . ContainsKey ( route . RouteName ) )
161+ {
162+ throw new InvalidOperationException ( $ "The route with name '{ route . RouteName } ' has already been registered!") ;
163+ }
138164
139- var virtualPath = group ? . VirtualPathPrefix ?? "" ;
140- AddCore ( routeName , url , virtualPath , defaultValues , presenterFactory , localizedUrls ) ;
165+ group ? . AddToParentRouteTable ? . Invoke ( route ) ;
166+
167+ // The list is used for finding the routes because it keeps the ordering, the dictionary is for checking duplicates
168+ list . Add ( new KeyValuePair < string , RouteBase > ( route . RouteName , route ) ) ;
169+ dictionary . Add ( route . RouteName , route ) ;
170+
171+ if ( route is IPartialMatchRoute partialMatchRoute )
172+ {
173+ partialMatchRoutes . Add ( partialMatchRoute ) ;
174+ }
141175 }
142176
143- private void AddCore ( string routeName , string ? url , string virtualPath , object ? defaultValues , Func < IServiceProvider , IDotvvmPresenter > ? presenterFactory , LocalizedRouteUrl [ ] ? localizedUrls )
177+ private void AddCore ( string routeName , string url , string ? virtualPath , object ? defaultValues , Func < IServiceProvider , IDotvvmPresenter > ? presenterFactory , LocalizedRouteUrl [ ] ? localizedUrls = null )
144178 {
179+ ThrowIfFrozen ( ) ;
180+
181+ if ( url == null )
182+ throw new ArgumentNullException ( nameof ( url ) ) ;
145183 url = CombinePath ( group ? . UrlPrefix , url ) ;
184+
185+ virtualPath = CombinePath ( group ? . VirtualPathPrefix , virtualPath ) ;
186+ if ( virtualPath == null && presenterFactory == null )
187+ {
188+ throw new ArgumentNullException ( nameof ( presenterFactory ) , "The presenterFactory argument must be set when virtualPath is null!" ) ;
189+ }
190+
146191 presenterFactory ??= GetDefaultPresenter ;
147192 routeName = group ? . RouteNamePrefix + routeName ;
148193
149194 RouteBase route = localizedUrls == null
150- ? new DotvvmRoute ( url , virtualPath , defaultValues , presenterFactory , configuration )
195+ ? new DotvvmRoute ( url , virtualPath , routeName , defaultValues , presenterFactory , configuration )
151196 : new LocalizedDotvvmRoute ( url ,
152197 localizedUrls . Select ( l => new LocalizedRouteUrl ( l . CultureIdentifier , CombinePath ( group ? . UrlPrefix , l . RouteUrl ) ) ) . ToArray ( ) ,
153- virtualPath , defaultValues , presenterFactory , configuration ) ;
154- Add ( routeName , route ) ;
198+ virtualPath , routeName , defaultValues , presenterFactory , configuration ) ;
199+ Add ( route ) ;
155200 }
156201
157202 /// <summary>
@@ -171,7 +216,6 @@ public void AddUrlRedirection(string routeName, string urlPattern, string target
171216 /// <param name="targetUrlProvider">URL provider to obtain context-based redirection targets.</param>
172217 public void AddUrlRedirection ( string routeName , string urlPattern , Func < IDotvvmRequestContext , string > targetUrlProvider , object ? defaultValues = null , bool permanent = false )
173218 {
174- ThrowIfFrozen ( ) ;
175219 IDotvvmPresenter presenterFactory ( IServiceProvider serviceProvider ) => new DelegatePresenter ( context =>
176220 {
177221 var targetUrl = targetUrlProvider ( context ) ;
@@ -181,7 +225,7 @@ public void AddUrlRedirection(string routeName, string urlPattern, Func<IDotvvmR
181225 else
182226 context . RedirectToUrl ( targetUrl ) ;
183227 } ) ;
184- Add ( routeName , new DotvvmRoute ( urlPattern , string . Empty , defaultValues , presenterFactory , configuration ) ) ;
228+ AddCore ( routeName , urlPattern , virtualPath : null , defaultValues , presenterFactory ) ;
185229 }
186230
187231 /// <summary>
@@ -207,7 +251,6 @@ public void AddRouteRedirection(string routeName, string urlPattern, Func<IDotvv
207251 object ? defaultValues = null , bool permanent = false , Func < IDotvvmRequestContext , Dictionary < string , object ? > > ? parametersProvider = null ,
208252 Func < IDotvvmRequestContext , string > ? urlSuffixProvider = null )
209253 {
210- ThrowIfFrozen ( ) ;
211254 IDotvvmPresenter presenterFactory ( IServiceProvider serviceProvider ) => new DelegatePresenter ( context =>
212255 {
213256 var targetRouteName = targetRouteNameProvider ( context ) ;
@@ -219,50 +262,7 @@ public void AddRouteRedirection(string routeName, string urlPattern, Func<IDotvv
219262 else
220263 context . RedirectToRoute ( targetRouteName , newParameterValues , urlSuffix : urlSuffix ) ;
221264 } ) ;
222- Add ( routeName , new DotvvmRoute ( urlPattern , string . Empty , defaultValues , presenterFactory , configuration ) ) ;
223- }
224-
225- /// <summary>
226- /// Adds the specified route name.
227- /// </summary>
228- /// <param name="routeName">Name of the route.</param>
229- /// <param name="url">The URL.</param>
230- /// <param name="presenterType">The presenter factory.</param>
231- /// <param name="defaultValues">The default values.</param>
232- public void Add ( string routeName , string ? url , Type presenterType , object ? defaultValues = null , LocalizedRouteUrl [ ] ? localizedUrls = null )
233- {
234- ThrowIfFrozen ( ) ;
235- if ( ! typeof ( IDotvvmPresenter ) . IsAssignableFrom ( presenterType ) )
236- {
237- throw new ArgumentException ( $@ "{ nameof ( presenterType ) } has to inherit from DotVVM.Framework.Hosting.IDotvvmPresenter.", nameof ( presenterType ) ) ;
238- }
239- Func < IServiceProvider , IDotvvmPresenter > presenterFactory = provider => ( IDotvvmPresenter ) provider . GetRequiredService ( presenterType ) ;
240- Add ( routeName , url , presenterFactory , defaultValues , localizedUrls ) ;
241- }
242-
243- /// <summary>
244- /// Adds the specified name.
245- /// </summary>
246- public void Add ( string routeName , RouteBase route )
247- {
248- ThrowIfFrozen ( ) ;
249- if ( dictionary . ContainsKey ( routeName ) )
250- {
251- throw new InvalidOperationException ( $ "The route with name '{ routeName } ' has already been registered!") ;
252- }
253- // internal assign routename
254- route . RouteName = routeName ;
255-
256- group ? . AddToParentRouteTable ? . Invoke ( routeName , route ) ;
257-
258- // The list is used for finding the routes because it keeps the ordering, the dictionary is for checking duplicates
259- list . Add ( new KeyValuePair < string , RouteBase > ( routeName , route ) ) ;
260- dictionary . Add ( routeName , route ) ;
261-
262- if ( route is IPartialMatchRoute partialMatchRoute )
263- {
264- partialMatchRoutes . Add ( partialMatchRoute ) ;
265- }
265+ AddCore ( routeName , urlPattern , virtualPath : null , defaultValues , presenterFactory ) ;
266266 }
267267
268268 public void AddPartialMatchHandler ( IPartialMatchRouteHandler handler )
@@ -309,16 +309,21 @@ IEnumerator IEnumerable.GetEnumerator()
309309 return GetEnumerator ( ) ;
310310 }
311311
312- private string CombinePath ( string ? prefix , string ? appendedPath )
312+ [ return : NotNullIfNotNull ( nameof ( appendedPath ) ) ]
313+ private string ? CombinePath ( string ? prefix , string ? appendedPath )
313314 {
314315 if ( string . IsNullOrEmpty ( prefix ) )
315316 {
316- return appendedPath ?? "" ;
317+ return appendedPath ;
317318 }
318319
319- if ( string . IsNullOrEmpty ( appendedPath ) )
320+ if ( appendedPath == null )
321+ {
322+ return null ;
323+ }
324+ else if ( appendedPath == string . Empty )
320325 {
321- return prefix ! ;
326+ return prefix ?? string . Empty ;
322327 }
323328
324329 return $ "{ prefix } /{ appendedPath } ";
0 commit comments