ASP.NET 核心 Razor 页面路由参数
ASP.NET Core Razor Pages Routing With parameters
我有一个简单的页面,用户可以在其中根据开始日期和结束日期搜索记录,参考和客户字段是可选的
详情页我有这个
@page "{datestart}/{dateend}/{referenceId?}/{client?}"
在搜索页面上我有这个 post 处理程序
public IActionResult OnPost()
{
if (!ModelState.IsValid)
{
var options = new MemoryCacheEntryOptions() { AbsoluteExpiration = DateTime.Now.AddMinutes(10) };
ViewData["ReferenceId"] = new SelectList(_context.Referencias.AsNoTracking().FromCache(), "Id", "Name");
return Page();
}
return RedirectToPage("Details", new
{
datestart= SearchViewModel.DateStart.ToString("dd-MM-yyyy"),
dateend = SearchViewModel.DateEnd.ToString("dd-MM-yyyy"),
referenceId = SearchViewModel.ReferenceId,
client = SearchViewModel.Client
});
}
然而一切正常,除非引用字段为空
在我的详细信息页面上
public void OnGet(string datestart, string dateend, int? referenceId, int? client)
预期的结果是,如果我确实提供了客户但不提供 referenceId 事件,我将能够转到详细信息页面。
尽管日期始终是必需的。
那么有没有一种方法,即使没有提供 referenceId 但客户端提供了,我仍然可以路由?
我得到的只是这个异常
InvalidOperationException: No page named 'Details' matches the
supplied values.
Microsoft.AspNetCore.Mvc.Infrastructure.RedirectToPageResultExecutor.ExecuteAsync(ActionContext
context, RedirectToPageResult result)
Microsoft.AspNetCore.Mvc.RedirectToPageResult.ExecuteResultAsync(ActionContext
context)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeResultAsync(IActionResult
result)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResultFilterAsync()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResultExecutedContext
context)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.ResultNext(ref State next, ref Scope scope, ref object state, ref
bool isCompleted)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeResultFilters()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResourceFilter()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext
context) Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(ref
State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync()
Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke(HttpContext
httpContext)
Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware.Invoke(HttpContext
httpContext)
Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext
context)
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext
context)
NToastNotify.NtoastNotifyAjaxToastsMiddleware.InvokeAsync(HttpContext
context, RequestDelegate next)
Microsoft.AspNetCore.Builder.UseMiddlewareExtensions+<>c__DisplayClass5_1+<b__1>d.MoveNext()
Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext
context)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext
context)
我还尝试切换 {referenceId?} 和 {client?} 的顺序,它起作用了,但如果我对 referenceId 做同样的事情,它就会失败。
更新
根据@Nick 的建议,我再次尝试了多条路线,除了第二条路线,如果它是唯一的路线,它不会路线。
options.Conventions.AddAreaPageRoute("Production","/BackOffice/Account/Records/Details", "{datestart}/{dateend}/{client?}");
options.Conventions.AddAreaPageRoute("Production", "/BackOffice/Account/Records/Details", "{datestart}/{dateend}/{referenceId?}");
options.Conventions.AddAreaPageRoute("Production", "/BackOffice/Account/Records/Details", "{datestart}/{dateend}/{client?}/{referenceId?}");
这可能是一种奇怪的方式,但您可以使用 AddPageRoute 方法添加一个额外的根。
services.AddMvc().AddRazorPagesOptions(options =>
{
options.Conventions.AddPageRoute("/details", "{datestart}/{dateend}/{client?}");
});
如果您需要能够满足 referenceid
或 clientid
或两者的要求,您可以将第一个参数设为必需并传入 0,或者您可以使用请求参数。否则路由无法知道 /details/2019-8-15/2019-8-16/42
末尾的 42
是 clientid
还是 referenceid
值。
正如您所发现的,就路由而言
"{datestart}/{dateend}/{client?}"
与
相同
"{datestart}/{dateend}/{referenceid?}"
并会生成一个 AmbiguousActionException
.
如果要将第一个参数设为必填,方法如下:
@page "{datestart}/{dateend}/{referenceid:int=0}/{client?}"
标签助手内部生成的任何 link 将自动用 0
填充 referenceid
段,除非提供另一个值。
我有一个简单的页面,用户可以在其中根据开始日期和结束日期搜索记录,参考和客户字段是可选的
详情页我有这个
@page "{datestart}/{dateend}/{referenceId?}/{client?}"
在搜索页面上我有这个 post 处理程序
public IActionResult OnPost()
{
if (!ModelState.IsValid)
{
var options = new MemoryCacheEntryOptions() { AbsoluteExpiration = DateTime.Now.AddMinutes(10) };
ViewData["ReferenceId"] = new SelectList(_context.Referencias.AsNoTracking().FromCache(), "Id", "Name");
return Page();
}
return RedirectToPage("Details", new
{
datestart= SearchViewModel.DateStart.ToString("dd-MM-yyyy"),
dateend = SearchViewModel.DateEnd.ToString("dd-MM-yyyy"),
referenceId = SearchViewModel.ReferenceId,
client = SearchViewModel.Client
});
}
然而一切正常,除非引用字段为空
在我的详细信息页面上
public void OnGet(string datestart, string dateend, int? referenceId, int? client)
预期的结果是,如果我确实提供了客户但不提供 referenceId 事件,我将能够转到详细信息页面。
尽管日期始终是必需的。
那么有没有一种方法,即使没有提供 referenceId 但客户端提供了,我仍然可以路由?
我得到的只是这个异常
InvalidOperationException: No page named 'Details' matches the supplied values. Microsoft.AspNetCore.Mvc.Infrastructure.RedirectToPageResultExecutor.ExecuteAsync(ActionContext context, RedirectToPageResult result) Microsoft.AspNetCore.Mvc.RedirectToPageResult.ExecuteResultAsync(ActionContext context) Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeResultAsync(IActionResult result) Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResultFilterAsync() Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResultExecutedContext context) Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.ResultNext(ref State next, ref Scope scope, ref object state, ref bool isCompleted) Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeResultFilters() Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResourceFilter() Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context) Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted) Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync() Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync() Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke(HttpContext httpContext) Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware.Invoke(HttpContext httpContext) Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context) Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context) NToastNotify.NtoastNotifyAjaxToastsMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) Microsoft.AspNetCore.Builder.UseMiddlewareExtensions+<>c__DisplayClass5_1+<b__1>d.MoveNext() Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context) Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
我还尝试切换 {referenceId?} 和 {client?} 的顺序,它起作用了,但如果我对 referenceId 做同样的事情,它就会失败。
更新
根据@Nick 的建议,我再次尝试了多条路线,除了第二条路线,如果它是唯一的路线,它不会路线。
options.Conventions.AddAreaPageRoute("Production","/BackOffice/Account/Records/Details", "{datestart}/{dateend}/{client?}");
options.Conventions.AddAreaPageRoute("Production", "/BackOffice/Account/Records/Details", "{datestart}/{dateend}/{referenceId?}");
options.Conventions.AddAreaPageRoute("Production", "/BackOffice/Account/Records/Details", "{datestart}/{dateend}/{client?}/{referenceId?}");
这可能是一种奇怪的方式,但您可以使用 AddPageRoute 方法添加一个额外的根。
services.AddMvc().AddRazorPagesOptions(options =>
{
options.Conventions.AddPageRoute("/details", "{datestart}/{dateend}/{client?}");
});
如果您需要能够满足 referenceid
或 clientid
或两者的要求,您可以将第一个参数设为必需并传入 0,或者您可以使用请求参数。否则路由无法知道 /details/2019-8-15/2019-8-16/42
末尾的 42
是 clientid
还是 referenceid
值。
正如您所发现的,就路由而言
"{datestart}/{dateend}/{client?}"
与
相同"{datestart}/{dateend}/{referenceid?}"
并会生成一个 AmbiguousActionException
.
如果要将第一个参数设为必填,方法如下:
@page "{datestart}/{dateend}/{referenceid:int=0}/{client?}"
标签助手内部生成的任何 link 将自动用 0
填充 referenceid
段,除非提供另一个值。