【问题标题】:One-to-many relationship in the create action methodcreate action 方法中的一对多关系
【发布时间】:2014-02-12 02:41:32
【问题描述】:

我目前正在处理一个需要为一个客户添加多个地址的项目。 我有三个模型: 这是我的类图的链接:http://sdrv.ms/1fWioA2

人物模型:

public class Person
{    
    public Person()
    {
        this.Adresses = new HashSet<Address>();
    }

    public int PersonID { get; set; }

    [Required(ErrorMessage = "Name is required")]
    public string Name { get; set; }

    [Required(ErrorMessage = "Email Address is required")]
    [DisplayName("Email Address")]
    //[RegularExpression(@"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}",
    //ErrorMessage = "Email is is not valid.")]
    [DataType(DataType.EmailAddress)]
    public string Email { get; set; }

    public string Mobile { get; set; }
    public string Phone { get; set; }
    public string Fax { get; set; }

    public virtual ICollection<Address> Adresses { get; set; }
}

地址:

public class Address
{
    [HiddenInput(DisplayValue = false)]
    public int ID { get; set; }
    public string Street { get; set; }
    public string Building  { get; set; }

    public int PersonID { get; set; }
    public int CityID { get; set; }

    public virtual City City { get; set; }
    public virtual Person Person { get; set; }
}

我创建了模型视图以绑定到我的创建视图:

public class PersonViewModel
{
    public Person Person { get; set; }
    public ICollection<Address> Adresses { get; set; }
} 

我的问题是如何将视图模型绑定到创建视图,以便能够为同一个 Person 保存多个地址?

【问题讨论】:

    标签: asp.net asp.net-mvc asp.net-mvc-4


    【解决方案1】:

    为此,在/Shared/Editor 中创建一个名为Address.cshtml 的编辑器模板:

    @model Address
    
    <div class="address">
    @Html.HiddenFor(model => model.ID)
    @Html.HiddenFor(model => model.PersonID)
    @Html.HiddenFor(model => model.CityID)
    @Html.TextBoxFor(model => model.Street) <br />
    @Html.TextBoxFor(model => model.Building  ) <br />
    </div>
    

    现在,在您的View 中,您需要做的就是:

    @Html.EditorFor(v => v.Addresses)
    

    这将创建如下表单字段:

    <input type="hidden" name="address[0].Id" />
    <input type="hidden" name="address[0].PersonId" />
    <input type="hidden" name="address[0].CityId" />
    <input type="text" name="address[0].Street" />
    <input type="text" name="address[0].Building" />
    <input type="hidden" name="address[1].Id" />
    <input type="hidden" name="address[1].PersonId" />
    <input type="hidden" name="address[1].CityId" />
    <input type="text" name="address[1].Street" />
    <input type="text" name="address[1].Building" />
    

    模型绑定将看到这些字段符合 ASP.Net 有线格式,并将这些字段的值绑定到地址集合中。参考:http://www.hanselman.com/blog/ASPNETWireFormatForModelBindingToArraysListsCollectionsDictionaries.aspx

    如果您开始使用 Javascript 处理字段,请小心。如果动态添加或删除地址块,则必须确保将索引重置为从零开始,并且索引始终以 1 递增。

    【讨论】:

    • 我应该将视图绑定到 Person 模型还是 PersonViewModel ?
    • 你应该将你的视图绑定到一个视图模型——这就是他们的目的!有时你的领域模型可以用来输入你的视图,但更多时候你想塑造你的视图使用的模型,这就是视图模型的用武之地。
    • 我无法获取地址后的前缀...地址[0].Id,我得到的只是地址.ID
    • 那么Addresses是一个集合,里面有多个地址?
    【解决方案2】:

    我建议您使用以淘汰赛为例的客户端方法: 服务器端:

     public class HomeController : Controller
    {
        //
        // GET: /Home/
    
        public ActionResult Index()
        {
            var model = new
            {
                person = new { firstName = "123", secondName = "" },
                addresses = new dynamic[1] { new { street = "", building = "", selectedCityId = "" } },
                cities = new dynamic[2] { new { cityName = "Kiev", cityId = "1" }, new { cityName = "Moskow", cityId = "2" } }
    
            };
            return View(model);
        }
    
        public ActionResult Save(YourType model)
        {
            ..... 
        }
    
    }
    

    和客户端:

    @{
    Layout = null;
    }
    @using Newtonsoft.Json;
    
    <!DOCTYPE html>
    
    <html>
    <head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
    </head>
    <body>
    <div style="margin-left:100px">
        <p>First name:</p>
        <input data-bind="value:person.firstName" />
    
        <p>Second name:</p>
        <input data-bind="value:person.secondName" />
        <h3>Addresses</h3>
        <div data-bind="foreach:addresses">
            <p>
                Street
            </p>
            <input data-bind="value:street" />
            <p>
                Building
            </p>
            <input data-bind="value:building" />
            <p>
                City
            </p>
            <select data-bind="options: $parent.cities, optionsText: 
               'cityName',optionsValue:'cityId',
                  value: selectedCityId , optionsCaption: 'Choose...'"></select>
            <div>
                <div style="float:left;">
                    <button data-bind="click:$parent.add">
                        Add
                    </button>
                </div>
                <div style="float:left;">
                    <button data-bind="click: $parent.remove">
                        Delete
                    </button>
                </div>
            </div>
            <div style="clear:both"></div>
        </div>
        <button style="width:100px"data-bind="click:save">
            Save
        </button>
    
     </div>
     <script src="~/Scripts/jquery-1.8.2.js"></script>
     <script src="~/Scripts/knockout-3.0.0.js"></script>
     <script src="~/Scripts/knockout.mapping-latest.js"></script>
     <script type="text/javascript">
        //This create javascript object from your model
        var personModel=@Html.Raw(JsonConvert.SerializeObject(Model))
        //Parse javascript object to knockout viewModel
        var viewModel=ko.mapping.fromJS(personModel);
        // Create new address
        function Address(){
            this.selectedCityId=ko.observable("");
            this.street=ko.observable("");
            this.building=ko.observable("");
        }
        //Add new address
        viewModel.add=function(){
            viewModel.addresses.push(new Address());
    
        };
        //Remove address
        viewModel.remove =function(item){
            if(viewModel.addresses().length>1){
                viewModel.addresses.remove(item)
            }         
        };
        //save model
        viewModel.save=function(){
            unmapped=ko.mapping.toJSON(viewModel);
            $.post('/home/save',unmapped)
        };
    
        ko.applyBindings(viewModel);
    </script>
    </body>
    </html>
    

    这里有一些链接http://blog.stevensanderson.com/2010/07/12/editing-a-variable-length-list-knockout-style/也使用这种方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-28
      • 2022-11-14
      • 1970-01-01
      相关资源
      最近更新 更多