【问题标题】:How to feature a page in another page?如何在另一个页面中显示一个页面?
【发布时间】:2018-04-22 09:53:44
【问题描述】:

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

CSHTML:

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

`InvalidOperationException:传入的模型项 ViewDataDictionary 的类型为“CS.Pages.Manifest.IndexModel”,但这 ViewDataDictionary 实例需要类型为模型项 'CS.Pages.Account.LoginModel'。

LoginModel 构造函数:

public LoginModel(SignInManager<ApplicationUser> signInManager, ILogger<LoginModel> logger)
{
    _signInManager = signInManager;
    _logger = logger;
}

【问题讨论】:

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


    【解决方案1】:

    当你加载一个像这样的部分时:

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

    您从中调用它的视图模型是隐式传入的,就像您已经完成一样:

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

    因此,您收到的错误。部分需要LoginModel 类型的模型,但您传递给它的是IndexModel 类型的模型。解决方案当然是传入正确类型的模型,即LoginModel。但是,您的LoginModel 必须使用SignInManager&lt;ApplicationUser&gt; 和ILogger&lt;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-returning InvokeAsync 的性质。如果你真的需要异步的东西,你可以在这里简单地等待。

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

    最后,在您希望它出现的地方,您只需调用:

    @await Component.InvokeAsync("Login");
    

    使用 is 方法,所有功能(包括模型的创建和传入)都是自包含的,因此可以在任何地方调用它,无论是在单独的视图中,还是在您的布局中.

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

      • 我有@model IndexModel,我需要索引模型,所以我得到One or more compilation references are missing. Ensure that your project is referencing 'Microsoft.NET.Sdk.Web' and the 'PreserveCompilationContext' property is not set to false.
      • 如果传递 null 而不是 LoginModel() 实例会怎样? -@await Html.PartialAsync("Account/Login", null)。我认为您收到了“InvalidOperationException”,因为 IndexModel 正在被传递到它期望 LoginModel 的登录视图中。我不明白你在评论中提到的第二个错误。你能详细说明你什么时候收到这个吗?
      • 当我使用`@await Html.PartialAsync("Account/Login", new LoginModel())` 我得到了这个There is no argument given that corresponds to the required formal parameter 'signInManager' of 'LoginModel.LoginModel(SignInManager&lt;ApplicationUser&gt;, ILogger&lt;LoginModel&gt;)'我试过nulll但它说The model item passed into the ViewDataDictionary is of type 'CS.Pages.IndexModel', but this ViewDataDictionary instance requires a model item of type 'CS.Pages.Account.LoginModel'.我已经添加了我的问题的登录构造函数。
      • 在将 null 模型转换为 LoginModel 后传递它应该可以解决该问题。 @await Html.PartialAsync("Account/Login", (LoginModel)null)。另一种选择是将其保留为 IndexModel 的属性并传递此链接中提到的内容 - stackoverflow.com/a/35927653/8879188
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多