ASP.NET MVC视图模型绑定:如何填充对象集合?

时间:2015-11-03 11:51:37

标签: asp.net-mvc model-binding

直到几天前,在我的应用程序中管理模型绑定非常容易。我有一个名为PersonOfferDTO的视图模型,其中包含PersonProductOfferDTO的集合。 (是的,我使用DTO作为视图模型,因为在这种情况下视图模型将等于DTO)。以下是PersonOfferDTO

的简化版本
public class PersonOfferDTO
{
    [DataMember]
    public Guid PersonOfferId { get; private set; }
    [DataMember]
    public ICollection<PersonProductOfferDTO> Offers { get; set; }
}

以下是PersonProductOfferDTO

的简化版本
public class PersonProductOfferDTO
{
    [DataMember]
    public Guid PersonProductOfferId { get; private set; }
    [DataMember]
    public Guid PersonOfferId { get; set; }
    [DataMember]
    public int Quantity { get; set; }
    [DataMember]
    public decimal UnitPrice { get; set; }
}

由于下面显示的方法(HTML代码),我能够填充ICollection

<form method="POST" action="/Offers/AddNewPersonOffer">

    <input name="PersonProductOffers.Index" value="myKey1" hidden>
    <input name="PersonProductOffers[myKey1].Quantity">
    <input name="PersonProductOffers[myKey1].UnitPrice">

    <input name="PersonProductOffers.Index" value="myKey2" hidden>
    <input name="PersonProductOffers[myKey2].Quantity">
    <input name="PersonProductOffers[myKey2].UnitPrice">

</form>

但是在最后几天我增加了对象树的深度,所以现在我有以下代码。

public class PersonOfferDTO
{
    [DataMember]
    public Guid PersonOfferId { get; private set; }
    [DataMember]
    public ICollection<PersonOfferParagraphDTO> Paragraphs { get; set; }
}

[DataContract]
public class PersonOfferParagraphDTO
{
    [DataMember]
    public Guid PersonOfferParagraphId { get; set; }
    [DataMember]
    public ICollection<PersonProductOfferDTO> PersonProductOffers { get; set; }
}

正如您所看到的,PersonOfferDTOPersonProductOfferDTO之间现在又有一个级别,我无法弄清楚如何执行&#34;多级绑定&#34;:创建PersonOfferDTO PersonOfferParagraphDTO,每个PersonProductOfferDTO包含更多public ActionResult AddNewPersonOffer(PersonOfferDTO offer) { if (!UserHasPermissions()) { return PartialView("_forbidden"); } var errors = OffersCRUD.AddNewPersonOffer(offer); if(errors.Count() == 0) { return RedirectToAction("Index"); } return PartialView("_errors", new ErrorsViewModel(errors)); }

注意:我不想使用增量索引([0],[1],....)...但是一个字符串([&#34;的myKey&#34;])

修改

根据要求,我在下面添加控制器

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations={"classpath*:context.xml"})
    @Component
    public class MyTest {

        @Autowired
        private Something something1;

        @Autowired
        private Something something2;
        ..

        @Test
        public void test1()
        {
            // something1 and something2 are fine
            new Helper().initDB();
            ..
        }
   }

// Same package
public class Helper {
   @Autowired
   private Something something1;

   @Autowired
   private Something something2;
   ..

   public void initDB()
    {
        // something1 and something2 are null. I have tried various annotations.
    }
}

1 个答案:

答案 0 :(得分:0)

如果要使用自己的密钥填充它们,可以在视图模型中将集合定义为Dictionary<string, YOURCLASS>,它接受​​非整数索引值。

使用词典的示例视图模型:

public class ViewModelTest
{
   public Dictionary<string, Class1> Values { get; set; }
}

要在字典集合中使用的示例类:

public class Class1
{
    public int MyProperty { get; set; }

    public Dictionary <string, Class2> MoreValues { get; set; }
}

public class Class2
{
    public int AnotherProperty { get; set; }
}

这是一个填充值的表单:

@using (Html.BeginForm())
{
    <input type="text" name="Values[yourkey1].MyProperty" />
    <input type="text" name="Values[yourkey1].MoreValues[anotherKey1].AnotherProperty" />

    <input type="text" name="Values[yourkey2].MyProperty" />
    <input type="text" name="Values[yourkey2].MoreValues[anotherKey2].AnotherProperty" />

    <input type="submit" />
}

除了自己编写input标签外,您可以使用辅助方法并享受智能感知,假设您在视图中定义的视图模型具有在操作方法中定义的相同结构:

@model ViewModelTest

@using (Html.BeginForm())
{ 
    @Html.TextBoxFor(x => x.Values[yourkey1].MyProperty)
    @Html.TextBoxFor(x => x.Values[yourkey1].MoreValues[anotherKey1].AnotherProperty)

    @Html.TextBoxFor(x => x.Values[yourkey2].MyProperty)
    @Html.TextBoxFor(x => x.Values[yourkey2].MoreValues[anotherKey2].AnotherProperty)

    <input type="submit" />
}

你必须为此引入一个视图模型,而不仅仅是使用你的DTO;)。

PS:DTO也不应该用作域模型,而是用于在您的图层周围传输信息。