我有以下代码段。
public async Task<ActionResult> Register(RegisterViewModel model)
{
if (!ModelState.IsValid) return View(model as LocalRegisterViewModel);
var user = new User
{
UserId = model.Username,
Password = null,
Email = model.Email,
AccType = model.AccountType
};
var modelAsLocalRegisterViewModel = model as LocalRegisterViewModel;
if (modelAsLocalRegisterViewModel != null)
user.Password = modelAsLocalRegisterViewModel.Password;
//...
}
这些课程如下所示。
public class RegisterViewModel
{
public string Username { get; set; }
public string Email { get; set; }
public int AccountType { get; set; }
}
public interface IInternalPassword
{
string Password { get; set; }
string ConfirmPassword { get; set; }
}
public class LocalRegisterViewModel : RegisterViewModel, IInternalPassword
{
public string Password { get; set; }
public string ConfirmPassword { get; set; }
}
LocalRegisterViewModel
从cshtml
页面传递给控制器,如下所示。
@model LocalRegisterViewModel
@{
ViewBag.Title = "Register";
Layout = "~/Views/Shared/_LayoutAnonymous.cshtml";
}
<h2>@ViewBag.Title.</h2>
@using (Html.BeginForm("Register", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
我的问题是,modelAsLocalRegisterViewModel
在安全演员之后为空。
var modelAsLocalRegisterViewModel = model as LocalRegisterViewModel;
if (modelAsLocalRegisterViewModel != null)
user.Password = modelAsLocalRegisterViewModel.Password;
有人可以调查并告诉我原因吗?
修改
似乎我的提问风格很糟糕。所以让我澄清我的确切意图。我编写的Register
操作旨在为多个ViewModel提供服务,每个ViewModel都有一些额外的信息。所以我所做的就是编写一个包含公共属性的父类,并扩展它以获得添加的属性。对于一个实例,我将一个LocalRegisterViewModel
的实例传递给控制器,以便它首先执行公共功能,如果传递的实例是LocalRegisterViewModel
类型,则执行扩展的功能即可。这就是我需要检查传递的RegisteredViewModel
的原因,也是LocalRegisterViewModel
类型。
编辑2 这不是试图将基类实例分配给派生类引用。事实上,以下内容在C#中完全有效。
class Program
{
static void Test(Parent p)
{
var c = p as Child;
Console.WriteLine(c == null ? "Can't do it!" : "Can do it!");
Console.WriteLine(c.GetType().ToString());
}
static void Main(string[] args)
{
var c = new Child();
Test(c);
}
}
public class Parent
{
}
public class Child : Parent
{
}
答案 0 :(得分:2)
右;所以如果:
var modelAsLocalRegisterViewModel = model as LocalRegisterViewModel;
给出null
,然后有两个选项:
model
是null
model
是一种东西,但不是LocalRegisterViewModel
所以:您需要查看model
并找出它是什么。我们无法告诉您:它不在显示的代码中。但是string typeName = model?.GetType()?.Name;
应该告诉你哪个;它会返回null
或model
类型的名称。
通过最近的修改,我们可以看到model
是RegisterViewModel
;但是:听起来它不是LocalRegisterViewModel
。由于存在继承树,因此model
听起来像基本类型(RegisterViewModel
)或与LocalRegisterViewModel
无关的不同子类型。< / p>
答案 1 :(得分:2)
我认为你的困惑来自于认为你是从cshtml页面“调用”控制器方法Register()
,并在那里“传递”你的模型。这不完全正确。
当您提交表单时,它会将所有输入发送到服务器,并将其发布到指定的URL。这些输入可能包含LocalRegisterViewModel
的属性,例如Password
。请求正文可能如下所示:
{"email": "my@email.com", "password": "bla" }
当请求到达服务器时,ASP.NET会查找与给定URL匹配的控制器操作。它看到匹配操作为Register()
,此操作接受RegisterViewModel
类型的参数。现在它尝试绑定该模型(从http请求填充其属性)。它绝对不知道在传入请求中有其他值,例如Password
。
因此asp.net将创建RegisterViewModel
的实例并填充其属性,忽略所有其余的(例如密码),因为请求本身中没有关于应该将其解析为哪种C#类型的信息。 / p>