Leo*_*ues 5 c# asp.net-core-mvc
因此,我正在使用身份验证模板编辑默认的 ASP.NET MVC,并且我正在尝试为其创建一个 ViewModel _PartialLogin.cshtml,以便显示名称而不是用户的电子邮件。我搜索了很多东西,但它们已经过时了,所以我希望有人能提供帮助。我什至不知道创建 ViewModel 是否是最佳选择。
这是LoginPartialViewModel:
namespace AplicacaoRoles2.Models.SharedViewModels
{
public class PartialLoginViewModel
{
[Required]
public string Nome { get; set; }
}
}
Run Code Online (Sandbox Code Playgroud)
_LoginPartial.cshtml:
@using Microsoft.AspNetCore.Identity
@using AplicacaoRoles2.Models
@model AplicacaoRoles2.Models.SharedViewModels.PartialLoginViewModel
@inject SignInManager<ApplicationUser> SignInManager
@inject UserManager<ApplicationUser> UserManager
@if (SignInManager.IsSignedIn(User))
{
<form asp-area="" asp-controller="Account" asp-action="Logout" method="post" id="logoutForm" class="navbar-right">
<ul class="nav navbar-nav navbar-right">
<li>
<a asp-area="" asp-controller="Manage" asp-action="Index" title="Manage">Hello @Html.DisplayFor(model => model.Nome) !</a>
</li>
Run Code Online (Sandbox Code Playgroud)
(...)
HomeController:
public class HomeController : Controller
{
private readonly ApplicationDbContext _context;
public HomeController(ApplicationDbContext context)
{
_context = context;
}
public async Task<IActionResult> Index()
{
PartialLoginViewModel model = new PartialLoginViewModel();
var userName = User.Identity.Name;
var applicationUser = await _context.ApplicationUser.SingleOrDefaultAsync(m => m.UserName == userName);
model.Nome = applicationUser.Nome;
return View(model);
}
Run Code Online (Sandbox Code Playgroud)
在_Layout.cshtml有这一部分有用:
@Html.Partial("_LoginPartial")
Run Code Online (Sandbox Code Playgroud)
(代码被简化为缩短了这个)
所以这在我打开时工作正常,Home/index因为它没有模型,但是一旦我进入一个带有模型的页面,它就会显示一个模型错误的东西。
我可以替换:
@Html.Partial("_LoginPartial")
Run Code Online (Sandbox Code Playgroud)
为了
@Html.Partial("_LoginPartial", new AplicacaoRoles2.Models.SharedViewModels.PartialLoginViewModel())
Run Code Online (Sandbox Code Playgroud)
但问题是我通过创建一个新实例丢失了信息......谢谢。
**像“Nome”这样的词没有拼错,它们是葡萄牙语
让我们首先看看您遇到的问题是什么,然后我们将应用修复程序。
问题/问题
The_LoginPartial.cshtml是从 the 调用的Shared/_Layout.cshtml,除非你改变了它;看来您没有更改它,因此它使用默认值。没关系,您不必更改它。当您访问时Home/Index,您创建一个实例PartialLoginViewModel并将其传递给Home/Index.cshtml。默认情况下,所有.cshtml文件都使用Shared/_Layout.cshtml本质上这就是您的PartialLoginViewModel传递方式:
Home/Index(控制器)=> Home/Index.cshtml => Shared/_Layout.cshtml => _LoginPartial.cshtml
因此,在上面,很明显_LoginPartial.cshtml最终会得到控制PartialLoginViewModel,这就是为什么当您访问 时它会起作用Home/Index。一切都好,花花公子:)
现在让我们看看当您访问另一个页面时会发生什么;说SomeController.SomeAction。让我们进一步想象另一个页面有一个类型为 的模型SomeModel。以下是SomeModel遗嘱的传递方式:
Some/SomeAction(控制器)=> Some/SomeAction.cshtml => Shared/_Layout.cshtml => _LoginPartial.cshtml
它失败了,因为_LoginPartial.cshtml期望一个具有 属性的模型PartialLoginViewModel,但你已经给出了它SomeModel。
不是解决办法
这是行不通的:
@Html.Partial("_LoginPartial", new AplicacaoRoles2.Models.SharedViewModels.PartialLoginViewModel())
Run Code Online (Sandbox Code Playgroud)
因为您正在向 发送正确的模型 (PartialLoginViewModel),但_LoginPartial它是一个新实例并且尚未设置属性。因此,Name(你拼写的Nome)将为空。
这也行不通:
@Html.Partial("_LoginPartial", Model)
Run Code Online (Sandbox Code Playgroud)
因为您从主视图向其发送不同类型的模型。
使固定
解决问题的一种方法是继承视图(视图模型)的所有模型,PartialLoginViewModel以便部分保持满意。
public class PartialLoginViewModel
{
[Required]
public string Nome { get; set; }
}
public class SomeModel : PartialLoginViewModel
{
// Code ...
}
Run Code Online (Sandbox Code Playgroud)
您还需要Name在所有控制器操作中填充该属性。因此,只需创建一个基类并从中继承所有控制器即可。像这样:
public class CustomController : Controller
{
protected virtual async Task<TModel> CreateModel<TModel>() where TModel : PartialLoginViewModel, new()
{
TModel model = new TModel();
var userName = User.Identity.Name;
var applicationUser = await _context.ApplicationUser.SingleOrDefaultAsync(m => m.UserName == userName);
// Set common properties
model.Nome = applicationUser.Nome;
return model;
}
}
Run Code Online (Sandbox Code Playgroud)
然后从上述控制器继承所有控制器,并始终调用上述控制器的CreateModel方法,以便它可以填充公共属性,如下所示:
public class EveryoneOfYourControllers : CustomController
{
public async Task<IActionResult> Index()
{
var model = await base.CreateModel<SomeModel>();
// Set other properties on your model
return View();
}
}
Run Code Online (Sandbox Code Playgroud)
所有代码都位于一处。将来,如果您决定向 中添加另一个属性PartialLoginViewModel,您只需在一个位置更改代码即可设置附加属性。
既然您知道了问题所在,您就可以提出不同的解决方案。