C# 如何从“编辑”视图中的表单传递DTO以编辑POST操作?

C# 如何从“编辑”视图中的表单传递DTO以编辑POST操作?,c#,asp.net-mvc,C#,Asp.net Mvc,我正在将CRUD用户管理添加到我的ASP.NET MVC应用程序中。我用的是身份。我使用DTO处理ApplicationUser属性,使用AutoMapper将UserDto映射到ApplicationUser,反之亦然。 当我尝试将DTO传递给Edit/POST操作时,从表单(从视图)返回,DTO的所有属性都是空的,除了Id 也就是说,在发布表单和调试应用程序时,作为参数传递给编辑操作的DTO的所有属性都为null,但Id是正确的除外 我可以将DTO传回控制器吗?我该怎么做 UserDTO.c

我正在将CRUD用户管理添加到我的ASP.NET MVC应用程序中。我用的是身份。我使用DTO处理ApplicationUser属性,使用AutoMapper将UserDto映射到ApplicationUser,反之亦然。 当我尝试将DTO传递给Edit/POST操作时,从表单(从视图)返回,DTO的所有属性都是空的,除了Id

也就是说,在发布表单和调试应用程序时,作为参数传递给编辑操作的DTO的所有属性都为null,但Id是正确的除外

我可以将DTO传回控制器吗?我该怎么做

UserDTO.cs

public class UserDto
{
    [Required]
    public string Id { get; set; }

    [Required]
    [StringLength(255)]
    [Display(Name = "First Name")]
    public string FirstName { get; set; }

    [Required]
    [StringLength(255)]
    public string Surname { get; set; }

    [Required]
    [EmailAddress]
    [Display(Name = "E-mail")]
    public string Email { get; set; }

    [Display(Name = "E-mail Confirmed")]
    public bool EmailConfirmed { get; set; }

    [Display(Name = "Lockout Enddate")]
    public DateTime? LockoutEndDateUtc { get; set; }

    [Display(Name = "Lockout Enabled")]
    public bool LockoutEnabled { get; set; }

    [Display(Name = "Access Failed Count")]
    public int AccessFailedCount { get; set; }

}
public class UserDetailsViewModel
{        
    public UserDto User { get; set; }
    public UserRolesViewModel UserRolesViewModel { get; set; }

    public UserDetailsViewModel(UserDto user)
    {
        User = user;
        UserRolesViewModel = new UserRolesViewModel(user.Id);
    }
}
DTO包含在传递给视图的ViewModel中。我使用相同的ViewModel查看用户的详细信息,效果良好:

UserDetailsViewModel.cs

public class UserDto
{
    [Required]
    public string Id { get; set; }

    [Required]
    [StringLength(255)]
    [Display(Name = "First Name")]
    public string FirstName { get; set; }

    [Required]
    [StringLength(255)]
    public string Surname { get; set; }

    [Required]
    [EmailAddress]
    [Display(Name = "E-mail")]
    public string Email { get; set; }

    [Display(Name = "E-mail Confirmed")]
    public bool EmailConfirmed { get; set; }

    [Display(Name = "Lockout Enddate")]
    public DateTime? LockoutEndDateUtc { get; set; }

    [Display(Name = "Lockout Enabled")]
    public bool LockoutEnabled { get; set; }

    [Display(Name = "Access Failed Count")]
    public int AccessFailedCount { get; set; }

}
public class UserDetailsViewModel
{        
    public UserDto User { get; set; }
    public UserRolesViewModel UserRolesViewModel { get; set; }

    public UserDetailsViewModel(UserDto user)
    {
        User = user;
        UserRolesViewModel = new UserRolesViewModel(user.Id);
    }
}
Users/Edit.cshtml

@model MyApp.ViewModels.UserDetailsViewModel
@{
ViewBag.Title=Model.User.FirstName+“”+Model.User.姓氏;
Layout=“~/Views/Shared/_Layout.cshtml”;
}
@使用(Html.BeginForm())
{
@Html.AntiForgeryToken()
@Html.HiddenFor(model=>model.User.Id)
@Html.ValidationSummary(true,“,new{@class=“has error”})
@LabelFor(model=>model.User.FirstName,htmlAttributes:new{@class=“control label”})
@EditorFor(model=>model.User.FirstName,new{htmlAttributes=new{@class=“form control boxed”})
@Html.ValidationMessageFor(model=>model.User.FirstName,“,new{@class=“has error”})
@LabelFor(model=>model.User.lasname,htmlAttributes:new{@class=“control label”})
@Html.EditorFor(model=>model.User.namite,new{htmlAttributes=new{@class=“form control boxed”})
@Html.ValidationMessageFor(model=>model.User.namname,“,new{@class=“has error”})
@LabelFor(model=>model.User.Email,htmlAttributes:new{@class=“control label”})
@EditorFor(model=>model.User.Email,new{htmlAttributes=new{@class=“form control boxed”})
@Html.ValidationMessageFor(model=>model.User.Email,“,new{@class=“has error”})
@LabelFor(model=>model.User.emailconfirm,htmlAttributes:new{@class=“control label”})
@EditorFor(model=>model.User.emailconfirm,new{htmlAttributes=new{@class=“checkbox”})
@Html.ValidationMessageFor(model=>model.User.emailconfirm,“,new{@class=“has error”})
@LabelFor(model=>model.User.LockoutEndDateUtc,htmlAttributes:new{@class=“control label”})
@EditorFor(model=>model.User.LockoutEndDateUtc,new{htmlAttributes=new{@class=“form control boxed”})
@Html.ValidationMessageFor(model=>model.User.LockoutEndDateUtc,“,新的{@class=“has error”})
@LabelFor(model=>model.User.LockoutEnabled,htmlAttributes:new{@class=“control label”})
@EditorFor(model=>model.User.LockoutEnabled)
@Html.ValidationMessageFor(model=>model.User.LockoutEnabled,“,新的{@class=“has error”})
@LabelFor(model=>model.User.AccessFailedCount,htmlAttributes:new{@class=“control label”})
@EditorFor(model=>model.User.AccessFailedCount,new{htmlAttributes=new{@class=“form control boxed”})
@Html.ValidationMessageFor(model=>model.User.AccessFailedCount,”,新的{@class=“has error”})
}
@ActionLink(“返回列表”、“索引”)
@Html.Partial(“_UserRoles”,Model.UserRolesViewModel)
@节脚本
{
@Scripts.Render(“~/bundles/Scripts用户角色”)

}
根据视图,您的模型是
MyApp.ViewModels.UserDetailsViewModel
,因此当您提交表单时,它会将UserDetailsViewModel模型发送到操作。但编辑操作需要UserDTO模型,因此绑定将由于模型不匹配而无法工作。您应该将UserDetailsViewModel作为编辑操作的输入参数,并从中读取UserDto,如下所示(更改了编辑操作的两行)


ASP.NET无法正确反序列化
UserDto
,因为HTTP请求变量与UserDto类中的属性不匹配。这种情况最有可能发生,因为请求值被标记为,例如,
User.FirstName
,而当您的cshtml页面转换为HTML时,仅标记为
FirstName
。问题的核心是,您将
UserDetailViewModel
关联为视图的模型,同时希望将更平坦的
UserDto的实例反序列化为

发出的HTML 让我们仔细看看。首先,这里是表单中的一个片段

<div class="form-group">
  @Html.LabelFor(model => model.User.Email, htmlAttributes: new { @class = "control-label" })
  @Html.EditorFor(model => model.User.Email, new { htmlAttributes = new { @class = "form-control boxed" } })
  @Html.ValidationMessageFor(model => model.User.Email, "", new { @class = "has-error"})
</div>

另外,请注意上面语法中的
Name
属性区分大小写。

不知道这是否有帮助,但它显示了在mvc中工作的dto:如果在控制器中的编辑方法中将参数更改为UserDetailsViewModel类型,那么模型绑定工作吗?谢谢,这就是它的要点,我现在明白了,该操作需要与传递给视图的模型相同的模型。我不能告诉你
@Html.EditorFor(model => model.User.Email, new { htmlAttributes = new { Name = "email", @class = "form-control boxed" } })