C# 模型绑定:安全强制转换返回null

C# 模型绑定:安全强制转换返回null,c#,types,casting,C#,Types,Casting,我有以下片段 public async Task<ActionResult> Register(RegisterViewModel model) { if (!ModelState.IsValid) return View(model as LocalRegisterViewModel); var user = new User { UserId = model.Username, Password = null,

我有以下片段

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;
    //...
}
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" }))
有人能调查一下并告诉我原因吗

编辑

看来我的提问方式不好。因此,让我澄清一下我的确切意图。我编写的
Register
操作旨在为多个ViewModels提供服务,每个ViewModels都有一些附加信息。因此,我所做的是编写一个带有公共属性的父级,并扩展它以获得添加的属性。对于一个实例,我将
LocalRegisterViewModel
的一个实例传递给控制器,以便它首先执行公共功能,如果传递的实例类型为
LocalRegisterViewModel
if,它将执行扩展功能。这就是为什么我需要检查传递的
RegisteredViewModel
也是类型
LocalRegisterViewModel

编辑2 这不是试图将基类实例分配给派生类引用。事实上,以下内容在C#中完全有效

对,;因此,如果:

var modelAsLocalRegisterViewModel = model as LocalRegisterViewModel;
给出
null
,则正好有两个选项:

  • model
    null
  • model
    是某种东西,但不是
    LocalRegisterViewModel
因此:您需要查看
模型
,并找出它是什么。我们不能告诉您:它不在显示的代码中。但是
string typeName=model?.GetType()?.Name应该告诉你哪个;它将返回
null
model
所属类型的名称


通过最近的编辑,我们可以看到
model
是一个
RegisterViewModel
;但是:听起来它不是一个
LocalRegisterViewModel
。因为有一个继承树,所以听起来像是
model
是基本类型(
RegisterViewModel
)或者是与
LocalRegisterViewModel
无关的不同的子类型;因此,如果:

var modelAsLocalRegisterViewModel = model as LocalRegisterViewModel;
给出
null
,则正好有两个选项:

  • model
    null
  • model
    是某种东西,但不是
    LocalRegisterViewModel
因此:您需要查看
模型
,并找出它是什么。我们不能告诉您:它不在显示的代码中。但是
string typeName=model?.GetType()?.Name应该告诉你哪个;它将返回
null
model
所属类型的名称



通过最近的编辑,我们可以看到
model
是一个
RegisterViewModel
;但是:听起来它不是一个
LocalRegisterViewModel
。因为有一个继承树,听起来像是
模型
要么是基类型(
RegisterViewModel
)要么是与
LocalRegisterViewModel

无关的不同的子类型,我想你的困惑来自于从cshtml页面“调用”控制器方法
Register()
,并“传递”你的模型。这不完全是真的

当您提交表单时,它会将所有输入发送到服务器,发送到指定的url。这些输入可能包括
LocalRegisterViewModel
的属性,例如
Password
。请求主体可能如下所示:

{"email": "my@email.com", "password": "bla" }
当请求到达服务器时,ASP.NET将查找与给定url匹配的控制器操作。它看到匹配的操作是
Register()
,该操作接受类型为
RegisterViewModel
的参数。现在它尝试绑定该模型(从http请求填充其属性)。它完全不知道传入请求中是否有其他值,例如
密码


因此asp.net将创建
RegisterViewModel的实例并填充其属性,忽略所有其他属性(如密码),因为请求本身没有关于应该解析为哪种C类型的信息。

我认为您的困惑来自于“调用”控制器方法
Register()
从cshtml页面,并在那里“传递”您的模型。这不完全是真的

当您提交表单时,它会将所有输入发送到服务器,发送到指定的url。这些输入可能包括
LocalRegisterViewModel
的属性,例如
Password
。请求主体可能如下所示:

{"email": "my@email.com", "password": "bla" }
当请求到达服务器时,ASP.NET将查找与给定url匹配的控制器操作。它看到匹配的操作是
Register()
,该操作接受类型为
RegisterViewModel
的参数。现在它尝试绑定该模型(从http请求填充其属性)。它完全不知道传入请求中是否有其他值,例如
密码


因此,asp.net将创建
RegisterViewModel的实例并填充其属性,忽略所有其他属性(如密码),因为请求本身没有关于应将其解析为哪个C类型的信息。

如果您不希望强制转换失败,那么不要将
用作
操作符,使用
(LocalRegisterViewModel)型号
。它将抛出一个异常,说明什么不能被转换成什么。请原谅我的不完整问题。我刚刚注意到丢失的部分。我已经更新了它。我认为
模型
永远不能
注册为
模型
。它是asp.net mvc控制器操作的参数,并从http请求绑定。因此,它将始终是类型
RegisteredViewModel
,而不是任何其他(子)类型。我认为,您的困惑来自于您以某种方式“调用”控制器方法,将您的模型传递到那里。这不完全是真的。当您提交表单时,它会将所有值发布到服务器。这些值可能包括的所有属性
{"email": "my@email.com", "password": "bla" }