代码之家  ›  专栏  ›  技术社区  ›  reustmd

ASP.NET MVC中在视图和控制器之间传递复杂数据时出现问题

  •  0
  • reustmd  · 技术社区  · 15 年前

    假设我有两个域对象:

    public class ObjectA
    {
        public ObjectB ObjectB;
    }
    
    public class ObjectB
    {
    }
    

    我还有一个视图,允许我创建一个新的ObjectA,其中包括从可能的ObjectB列表中选择一个ObjectB。

    我创建了一个新类,用这个可能性列表装饰ObjectA,我想这确实是我的视图模型。

    public class ObjectAViewModel
    {
        public ObjectA ObjectA { get; private set; }
        public SelectList PossibleSelectionsForObjectB { get; private set; }
    
        public ObjectAViewModel(ObjectA objectA, IEnumerable<Location> possibleObjectBs)
        {
            ObjectA = objectA;
            PossibleSelectionsForObjectB = new SelectList(possibleObjectBs, ObjectA.ObjectB);
        }
    }
    

    现在,构造我的视图和控制器的最佳方法是什么,以允许用户在视图中选择ObjectB,然后让控制器将ObjectA与该ObjectB选择一起保存(ObjectB已存在并已保存)?

    尝试的解决方案1:

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Create(ObjectAViewModel objectAViewModel)
    

    尝试的解决方案2:

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Create(ObjectA objectA)
    

    这里的问题是ObjectA.ObjectB属性为null。再一次,我想DropDownList选择可能会更新这个。

    谢谢

    2 回复  |  直到 11 年前
        1
  •  1
  •   Mark van Proctor    15 年前

    我使用的代码如下:

        [HttpPost]
        public ActionResult Create([Bind(Exclude = "Id")]ObjectA objectAToCreate)
        {
            try
            {
                Repository.AddObjectA(objectAToCreate);
                return RedirectToAction("Details", new { id = objectAToCreate.Id });
            }
            catch
            {
                return View();
            }
        }
    

    在存储库中使用以下代码(特定于实体框架):

        public void AddObjectA(ObjectA objectAToAdd)
        {
            objectAToAdd.ObjectB = GetObjectB(objectAToAdd.ObjectB.Id);
            _entities.AddToObjectAs(objectAToAdd);
            _entities.SaveChanges();
        }
    
        public void GetObjectB(int id)
        {
            return _entities.ObjectBs.FirstOrDefault(m => m.id == id);
        }
    

    根据您的说明,它实际上是从底层数据服务重新加载对象,但是我发现不需要使用ModelState来访问尝试的值。

            <p>
                <%= Html.LabelFor( f => f.ObjectB.Id) %>
                <%= Html.DropDownList("ObjectB.Id", new SelectList((IEnumerable)ViewData["ObjectBList"], "Id", "Descriptor"),"") %>
                <%= Html.ValidationFor( f => f.ObjectB, "*") %>
            </p>
    

    请注意,这可以改进为使用强类型ViewModel(我相信您已经这样做了),还可以为ObjectB创建自定义编辑器模板,以便可以使用以下方法进行调用:

    <%= Html.EditorFor( f => f.ObjectB ) %>
    
        2
  •  0
  •   reustmd    15 年前

    1. 使用Controller.ModelState从下拉列表中获取所选项目
    2. 从基础数据服务重新加载该ObjectB
    3. 保存对象a

    现在我的控制器方法如下所示:

    根据LukLed的评论编辑

       [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Create(ObjectA objectA, string objectBStr)
        {
            ObjectB objectB = _objBService.Get(objectBStr);
            objectA.ObjectB = objectB;
            _objAService.Save(objectA);
            return RedirectToAction("Details", new { id = objectA.Id });
        }