当您加载部分内容时:
@await Html.PartialAsync("Account/Login")
您从中调用它的视图模型是隐式传入的,就像您已经完成一样:
@await Html.PartialAsync("Account/Login", Model)
因此,您收到的错误。partial 需要一个 type 的模型,LoginModel
但你传递给它一个 type 的模型IndexModel
。解决方案当然是传入正确类型的模型,即LoginModel
. 但是,您LoginModel
必须使用类型参数SignInManager<ApplicationUser>
和ILogger<LoginModel
. 因此,为什么您在尝试通过时收到第二个错误new LoginModel()
。
首先,所有这一切实际上归结为对部分的不当使用。需要这种复杂实例化的部分实际上应该是一个视图组件,这将为您提供更多的设置灵活性并允许您进行注入,这正是您在这里需要的。
本质上,您只需创建一个继承ViewComponent
并实现该方法的类InvokeAsync
:
public class LoginViewComponent : ViewComponent
{
private readonly SignInManager<ApplicationUser> _signInManager;
private readonly ILogger<LoginModel> _logger;
public LoginViewComponent(SignInManager<ApplicationUser> signInManager, ILogger<LoginModel> logger)
{
_signInManager = signInManager;
_logger = logger;
}
public async Task<IViewComponentResult> InvokeAsync()
{
var model = await GetModelAsync().ConfigureAwait(false);
return View(model);
}
public Task<LoginModel> GetModelAsync()
{
return Task.FromResult(new LoginModel(_signInManager, _logger));
}
}
请注意,视图组件的构造函数采用实例化所需的参数LoginModel
。这允许框架注入这些依赖项。然后,构造函数只是将这些存储在一些私有字段中。
该InvokeAsync
方法调用GetModelAsync
以获取LoginModel
实例,然后返回使用此模型的视图。由于这里没有实际的异步工作需要完成,因此该GetModelAsync
方法只返回Task
从新 a 的结果中创建的 a LoginModel
。必须这样做以满足Task
-returning 的性质InvokeAsync
。如果你真的需要异步的东西,你可以在这里简单地等待。
有了它,您只需要创建视图Views\Shared\Components\Login\Default.cshtml
。这将包含您当前正在使用的部分视图的内容。这Login\Default.cshtml
部分是按照惯例。该目录是视图组件类的名称,减去ViewComponent
后缀,Default.cshtml
是它将在那里查找的默认视图。如果您愿意,可以自定义,但实际上没有理由这样做。
最后,在您希望它出现的地方,您只需调用:
@await Component.InvokeAsync("Login");
使用 is 方法,所有功能(包括模型的创建和传入)都是独立的,因此可以在任何地方调用,无论是在单个视图中,甚至是您的布局中。