所以我正在使用身份验证模板编辑默认的ASP.NET MVC,我正在尝试为_PartialLogin.cshtml
创建一个ViewModel,以显示名称而不是用户的电子邮件。我搜索了很多东西,但它们已经过时了,所以我希望有人可以提供帮助。我甚至不知道创建ViewModel是否是最佳选择。
这是LoginPartialViewModel
:
namespace AplicacaoRoles2.Models.SharedViewModels
{
public class PartialLoginViewModel
{
[Required]
public string Nome { get; set; }
}
}
_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>
(...)
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);
}
在_Layout.cshtml
上,这部分很有用:
@Html.Partial("_LoginPartial")
(简化代码以缩短此内容)
所以当我在Home/index
时,这工作正常,因为它不是模型,但是当我进入带有模型的页面时,它会显示模型错误。
我可以替换:
@Html.Partial("_LoginPartial")
的
@Html.Partial("_LoginPartial", new AplicacaoRoles2.Models.SharedViewModels.PartialLoginViewModel())
但问题是我通过创建新实例而丢失了信息...... 谢谢。
**像'Nome'这样的单词没有拼写错误,它们是葡萄牙语
答案 0 :(得分:2)
让我们先看看您遇到的问题是什么,然后我们将应用修复程序。
问题/问题
_LoginPartial.cshtml
从Shared/_Layout.cshtml
调用,除非您更改了它;它似乎你没有改变它所以它使用默认值。没关系,你不必改变它。当您访问Home/Index
时,您创建了PartialLoginViewModel
的实例并将其传递给Home/Index.cshtml
。默认情况下,所有.cshtml
个文件都使用Shared/_Layout.cshtml
,因此基本上这就是PartialLoginViewModel
传递的方式:
主页/索引(控制器) =&gt; 主页/ Index.cshtml =&gt; 共享/ _Layout.cshtml =&gt; _LoginPartial.cshtml
因此,在上文中,很明显_LoginPartial.cshtml
最终获得了PartialLoginViewModel
,这就是为什么它在您访问Home/Index
时有效。一切都很好,花花公子:)
现在让我们看看当你访问另一个页面时会发生什么;说SomeController.SomeAction
。让我们进一步想象另一个页面有一个SomeModel
类型的模型。以下是SomeModel
的传递方式:
部分/ SomeAction(控制器) =&gt; 部分/ SomeAction.cshtml =&gt; 共享/ _Layout.cshtml =&gt; _LoginPartial .cshtml
繁荣失败是因为_LoginPartial.cshtml
期待的是一个具有PartialLoginViewModel
属性的模型,而是你给它SomeModel
。
不是修复
这不起作用:
@Html.Partial("_LoginPartial", new AplicacaoRoles2.Models.SharedViewModels.PartialLoginViewModel())
因为您正在向_LoginPartial
发送正确的模型(PartialLoginViewModel),但它是一个新实例,并且尚未设置属性。因此,Name
(拼写为Nome
)将为空。
这也行不通:
@Html.Partial("_LoginPartial", Model)
因为您从主视图发送了不同类型的模型。
<强>修正强>
解决问题的一种方法是从PartialLoginViewModel
继承您的观点(视图模型)的所有模型,以便部分保持高兴。
public class PartialLoginViewModel
{
[Required]
public string Nome { get; set; }
}
public class SomeModel : PartialLoginViewModel
{
// Code ...
}
您还需要在所有控制器操作中填充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;
}
}
然后从上面的控制器继承所有控制器并始终调用上面控制器的CreateModel
方法,以便它可以填充公共属性,如下所示:
public class EveryoneOfYourControllers : CustomController
{
public async Task<IActionResult> Index()
{
var model = await base.CreateModel<SomeModel>();
// Set other properties on your model
return View();
}
}
所有代码都在一个地方。将来,如果您决定将另一个属性添加到PartialLoginViewModel
,则只需在一个位置更改代码即可设置其他属性。
现在你知道了这个问题,你可以提出不同的解决方案。
答案 1 :(得分:1)
您需要将ViewModel从View传递到PartialView,因此您也可以将ViewModel作为Index.cshtml的Model包含在内。您已经通过Controller将所需的ViewModel发送到View,因此您只需将该模型传递给Partial的构造函数。
@Html.Partial("_LoginPartial", Model)
这是ASP.NET核心MVC吗?如果是这样,您最好使用ViewComponent。
答案 2 :(得分:0)
选项一:
由于您将PartialLoginViewModel作为Home索引的主要模型传递,因此Home视图的索引还应包含以下此行作为模型:
@model AplicacaoRoles2.Models.SharedViewModels.PartialLoginViewModel
如果是这种情况,您只需将页面的“模型”对象传递到Home.cshtml视图中的任何视图中:
@Html.Partial("_LoginPartial", Model)
这里的模型应该代表从HomeController.cs传入的模型,包含用户的nome。
选项二:
另一种选择是使用ViewData。
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;
ViewData["userModel"] = model;
return View();
}
并使用此行导入模型:
@Html.Partial("_LoginPartial", ViewData["userModel"])