【问题标题】:ViewModel with complex property具有复杂属性的 ViewModel
【发布时间】:2014-01-12 16:45:36
【问题描述】:

我不确定如何让它发挥作用。我不知道如何在此 ViewModel 上为我的 Customer 属性创建 [Display(Name = "XXXX")]

public class CreateAccountViewModel
{
    [Required]
    public Customer Customer { get; set; }

    [Required]
    [Display(Name = "Username")]
    public string UserName { get; set; }

    [Required]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }

    [DataType(DataType.Password)]
    [Display(Name = "Confirm password")]
    public string ConfirmPassword { get; set; }
}

我应该为Customer 创建一个ViewModel 并引用它而不是Customer 对象吗?然后为所有属性创建Display()

如果是这样,映射是否会在提交时起作用?

我使用这个如下(sn-p):

<div class="form-group">
    @Html.LabelFor(m => m.Customer.CompanyName, new { @class = "col-md-2 control-label" })
    <div class="col-md-10">
        @Html.TextBoxFor(m => m.Customer.CompanyName, new { @class = "form-control" })
    </div>
</div>
<div class="form-group">
    @Html.LabelFor(m => m.Customer.CVR, new { @class = "col-md-2 control-label" })
    <div class="col-md-10">
        @Html.TextBoxFor(m => m.Customer.CVR, new { @class = "form-control" })
    </div>
</div>

我希望将“公司名称”更改为更好的名称,例如“公司名称”。 :-)

【问题讨论】:

    标签: c# asp.net asp.net-mvc viewmodel


    【解决方案1】:

    好的,我采用了不同的方法。我不确定这是否更优雅。在我的研究中,我遇到了 AutoMapper 并做到了这一点。如果有人对我的问题有更好的解决方案,请告诉我。 :-)

    public static class AutoMapperWebConfiguration
    {
        public static void Configure()
        {
            Mapper.Initialize(cfg =>
            {
                cfg.AddProfile(new CustomerMapper());
                cfg.AddProfile(new CustomerAddressMapper());
            });
        }
    }
    
    public class CustomerMapper : Profile
    {
        protected override void Configure()
        {
            Mapper.CreateMap<CustomerViewModel, Customer>().ForMember(customer => customer.Address, expression => expression.MapFrom(viewModel => viewModel.Address));
        }
    }
    
    public class CustomerAddressMapper : Profile
    {
        protected override void Configure()
        {
            Mapper.CreateMap<CustomerAddressViewModel, Address>();
        }
    }
    

    Global.asax:

    AutoMapperWebConfiguration.Configure();
    

    然后我的ViewModels

    public class CreateAccountViewModel
    {
        public CustomerViewModel Customer { get; set; }
    
        [Required]
        [Display(Name = "User name")]
        public string UserName { get; set; }
    
        [Required]
        [DataType(DataType.Password)]
        [Display(Name = "Password")]
        public string Password { get; set; }
    
        [DataType(DataType.Password)]
        [Display(Name = "Confirm password")]
        public string ConfirmPassword { get; set; }
    }
    
    public class CustomerViewModel
    {
        [Required]
        [Display(Name = "Company Name")]
        public String CompanyName { get; set; }
    
        [Required]
        [Display(Name = "CVR")]
        public String CVR { get; set; }
    
        [Required]
        [Display(Name = "First name")]
        public String FirstName { get; set; }
    
        [Required]
        [Display(Name = "Last name")]
        public String LastName { get; set; }
    
        [Required]
        [Display(Name = "Phone (mobile)")]
        public String Phone { get; set; }
    
        [Required]
        [Display(Name = "E-mail")]
        public String Email { get; set; }
    
        public CustomerAddressViewModel Address { get; set; }
    }
    
    public class CustomerAddressViewModel
    {
        [Required]
        [Display(Name = "Streey")]
        public String Street { get; set; }
    
        [Required]
        [Display(Name = "Postal code")]
        public String PostalCode { get; set; }
    
        [Required]
        [Display(Name = "City")]
        public String City { get; set; }
    
        [Required]
        [Display(Name = "Country")]
        public String Country { get; set; }
    }
    

    最后是我的action,它采用CreateAccountViewModel

    //
    // POST: /Account/Register
    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> Register(CreateAccountViewModel model)
    {
        if (ModelState.IsValid) {
            Customer customer = Mapper.Map<Customer>(model.Customer);
            var user = new ApplicationUser() { UserName = model.UserName, Customer = customer };
    
            var result = UserManager.Create(user, model.Password);
            if (result.Succeeded)
            {
                await SignInAsync(user, false);
                return RedirectToAction("Index", "Home");
            }
            else
            {
                AddErrors(result);
            }
        }
    
        // If we got this far, something failed, redisplay form
        return View(model);
    }
    

    【讨论】:

      【解决方案2】:

      你可以使用这个结构:

      [DisplayName("YourName")]
      public string UserName { get; set; }
      

      在你看来:

      @Html.DisplayNameFor(m => m.Customer.CompanyName, new { @class = "col-md-2 control-label" }))
      

      【讨论】:

      • 是的,但是如何将其映射到“客户”对象属性?
      【解决方案3】:

      像往常一样,如果我需要用这些子对象显示一些复杂的模型——我为这个对象创建另一个模型,在新模型中指定属性。然后指定此模型而不是 Customer 属性。

      @Html.LabelFor(m => m.Customer.CompanyName, new { @class = "col-md-2 control-label" })
      

      如果子模型有显示属性,应该可以正常工作。

      另一种方法是在您的域类下指定这些属性,但对我而言 - 我不喜欢使用 UI 属性来弄脏域对象

      【讨论】:

      • 那么,创建一个 CustomerViewModel 并使用它来代替 Customer 对象?
      • 是的,我通常是这样做的。如果我需要在另一个对象上显示 Customer 对象,那么我使用相同的模型 CustomerModel 对象。
      • +1... 虽然很多时候数据库 POCO 类似于显示版本,但您很快意识到您需要一个不同的 POCO 的 ViewModel,因为显示某些内容需要与显示版本的根本不同你扔进数据库。
      猜你喜欢
      • 2018-10-06
      • 1970-01-01
      • 1970-01-01
      • 2023-04-02
      • 1970-01-01
      • 2011-11-16
      • 1970-01-01
      • 2021-05-18
      • 1970-01-01
      相关资源
      最近更新 更多