如何在另一个页面中显示页面?

时间:2017-11-09 11:57:39

标签: c# asp.net-core razor-pages

在我的主页(索引)页面上,如果用户未登录,我希望登录表单直接位于我的主页,但如果用户已经登录,则将显示索引页面。如果我使用style此页面按预期加载,但是在帐户I等文件夹中的其他页面出现错误

CSHTML:

_LoginPartial
  

`InvalidOperationException:传递给的模型项   ViewDataDictionary的类型为' CS.Pages.Manifest.IndexModel',但是这个   ViewDataDictionary实例需要类型的模型项   ' CS.Pages.Account.LoginModel'

LoginModel构造函数:

@if (SignInManager.IsSignedIn(User))
{
    <p> Welcome to my website</p>
}
else
{
    @await Html.PartialAsync("Account/Login")
}

2 个答案:

答案 0 :(得分:2)

当您加载部分内容时:

@await Html.PartialAsync("Account/Login")

您调用它的视图模型是隐式传递的,就像您已经完成的那样:

@await Html.PartialAsync("Account/Login", Model)

因此,您收到的错误。部分期望LoginModel类型的模型,但您将其传递给IndexModel类型的模型。当然,解决方案是传递正确类型的模型,即LoginModel。但是,您的LoginModel必须使用SignInManager<ApplicationUser>ILogger<LoginModel类型的参数构建。因此,当您尝试仅传递new LoginModel()时,您收到第二个错误的原因。

所有这一切都归结为这首先是部分的不当使用。需要这种实例化复合体的部分应该是view component,这样可以让您在设置时获得更大的灵活性,并且允许您进行注射,这就是您所需要的。在这里需要。

基本上,您只需创建一个继承自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的结果创建的LoginModel。必须这样做才能满足Task - 返回InvokeAsync的性质。如果你真的需要异步的东西,你可以简单地等到这里。

有了这个,你只需要创建视图Views\Shared\Components\Login\Default.cshtml。哪个会包含您当前正在使用的部分视图的内容。 Login\Default.cshtml部分按惯例。该目录是视图组件类的名称,减去ViewComponent后缀,Default.cshtml是它将在那里查找的默认视图。如果您愿意,可以自定义,但实际上没有理由。

最后,只要您想要显示,只需致电:

@await Component.InvokeAsync("Login");

使用is方法,所有功能(包括模型的创建和传递)都是自包含的,因此可以将其称为任何地方,无论是在单个视图中,还是在您的布局中

答案 1 :(得分:1)

尝试将LoginModel实例传递给局部视图

@if (SignInManager.IsSignedIn(User))
{
    <p> Welcome to my website</p>
}
else
{
    @await Html.PartialAsync("Account/Login", new LoginModel())
}