C# 如何在ASP.NET Core 3的Blazor页面中正确重用具有授权的控制器
先决条件:C# 如何在ASP.NET Core 3的Blazor页面中正确重用具有授权的控制器,c#,asp.net-core,asp.net-web-api,blazor,blazor-server-side,C#,Asp.net Core,Asp.net Web Api,Blazor,Blazor Server Side,先决条件: 单个ASP.NET Core 3 preview 8项目,包括Blazor服务器端和Web Api控制器 ASP.NET核心标识 浏览器中以及从移动客户端调用API时用于授权逻辑的Cookie和JWT令牌身份验证方案 为了简洁起见,这里的所有代码示例都有最少的代码量 这里是初始blazor页面、模型和初始控制器 @page”/fetchdata @属性[授权] @使用BlazorApp2.Controllers 呼叫控制器 @代码{ 专用异步任务callController() {
@page”/fetchdata
@属性[授权]
@使用BlazorApp2.Controllers
呼叫控制器
@代码{
专用异步任务callController()
{
}
}
公共类输入模型
{
[必需]
公共字符串消息{get;set;}
}
[路由(“api/[控制器]”)]
[ApiController]
[授权]
公共类MessageController:ControllerBase
{
[HttpPost(“createMessage”)]
公共异步任务CreateMessage(InputModel模型)
{
var userId=User.FindFirstValue(ClaimTypes.NameIdentifier);
返回$“{model.Message}{userId}”;
}
}
以“正常”的方式使用控制器(通过发送http请求)带来的内置好处很少:自动授权;模型验证;填充HttpContext和用户属性(以及其他)
目标是在获取Blazor页面的数据时重用控制器
想法1
配置控制器并将其注入Blazor页面,使其操作的调用方式与http请求期间的调用方式类似。不确定如何实现这一点,以及这是否确实可行。向DI容器注册控制器不是问题(addControllerAsservices()
)。但这不会在注入期间填充控制器的HttpContext
和User
属性。在控制器注入后获取HttpContext
的唯一方法(我知道)是在Startup
中配置IHttpContextAccessor
(services.AddHttpContextAccessor();
)并将其注入控制器。但这也意味着当使用http请求访问控制器时,可以从注入的IHttpContextAccessor
和控制器的HttpContext
属性访问HttpContext
。是否有任何可能的问题,因为这?此解决方案也不会在控制器中进行模型验证。同时,可以在从Blazor页面发送之前验证模型,但我不确定在这种情况下是否必须在controller中手动重新验证它
[路由(“api/[控制器]”)]
[ApiController]
[授权]
公共类MessageController:ControllerBase
{
专用只读IHttpContextAccessor\u httpContextAccessor;
公共消息控制器(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor=httpContextAccessor;
}
[HttpPost(“createMessage”)]
公共异步任务CreateMessage(InputModel模型)
{
var userId=_httpContextAccessor.HttpContext.User.FindFirstValue(ClaimTypes.nameignifier);
返回$“{model.Message}{userId}”;
}
}
@page”/fetchdata
@使用BlazorApp2.Controllers
@属性[授权]
@注入MessageController消息控制器;
呼叫控制器
@代码{
专用异步任务callController()
{
var结果=(等待消息控制器
.CreateMessage(新输入模型{Message=“Hello”})).Value;
}
}
创意2
使用HttpClient向控制器发出http请求。这里有2个问题。A) 不确定如何在DI容器中注册HttpClient
,这样所有必需的身份验证cookie将自动添加到每个调用中;B) 从性能角度来看,可能不是理想的解决方案,因为呼叫将离开服务器应用程序(在blazor页面中),并返回到同一应用程序(在controller中)
怎么走?还有其他更好的办法吗?我的想法中遗漏了什么