如何以一种形式发布两个或更多模型?

时间:2017-01-25 10:10:49

标签: c# .net asp.net-mvc entity-framework ef-database-first

我正在为项目制作互联网课程计划申请表。课程计划是根据以下模型构建的(使用Database First方法中的Entity Framework生成):

public partial class Subject
{
    public int Id { get; set; }
    public string Hour { get; set; }
    public string Name { get; set; }
    public int DayId { get; set; }
    [Required]
    public int PlanId { get; set; }

    public virtual Day Day { get; set; }
    public virtual Plan Plan { get; set; }
}

public partial class Plan
{
    public Plan()
    {
        this.Przedmiot = new HashSet<Subjects>();
    }

    public int Id { get; set; }
    [Required]
    public string Name { get; set; }

    public virtual ICollection<Subject> Subject { get; set; }
}

我在一个视图中显示两个模型没有问题,但我似乎无法弄清楚如何在创建新计划时将两个模型发布到数据库。我希望我的View看起来像这样: My View

所以我的问题是这里最好的方法是什么,如何在数据库的Plan表中创建一条记录,并在这一个视图中链接到它的许多主题记录。

编辑: 代码与我的显示按要求查看(省略了不必要的部分,因为它相当长):

@model IEnumerable<Lesson_plan.DAL.Subject>
<table style="border: 1px solid black; margin: 40px; width: 100%;">
    <tr>
        <th>Hours</th>
        <th>Monday</th>
        <th>Tuesday</th>
        <th>Wednesday</th>
        <th>Thursday</th>
        <th>Friday</th>
        <th>Saturday</th>
        <th>Sunday</th>
    </tr>

    @{
        if (Model != null)
        {
            var r = 1;
            var t = 1;
            List<string> hours = new List<string>();
            foreach (var subject in Model)
            {
                if (!hours.Contains(subject.Hour))
                {
                    <tr>
                        <td>
                            <textarea>    
                            @Html.DisplayFor(modelItem => subjest.Hour)
                            @{ hours.Add(subject.Hour); }
                            </textarea>
                        </td>

                        <td>
                            <textarea>  
                            @foreach (var subjectName in Model)
                            {
                                if (subjectName.Day.DayOfTheWeek.Equals("Monday") &&
                                    subject.Hour.Equals(subjetName.Hour))
                                {
                                    @Html.DisplayFor(modelItem => subject.Name)
                                }
                            }   
                            </textarea>
                        </td>

//and so on for every day 

                        }
                    </tr>
                    r++;
                }
            }
        }
    }
</table>

我的Controller类的代码(我使用Create方法进行了一些实验,但我在这里发布了原始方法):

namespace Lesson_plan.Controllers
{
    public class PlansController : Controller
    {
        private readonly LessonPlanEntities db = new LessonPlanEntities();

        // GET: Plans
        public ActionResult Index()
        {
            var plans = db.Plan.ToList();
            return View(plans);
        }

        // GET: Plans/Details/5
        public ActionResult Details(int? id)
        {
            if (id == null)
                return Create();
            var subjects = db.Subject.
                Where(x => x.PlanId == id).
                OrderByDescending(x => x.Hour).ToList();
            if (subjects.Count > 0)
                ViewBag.Title = subjects[0].Plan.Name;
            return View(subjects);
        }

        // GET: Plans/Create
        public ActionResult Create()
        {
            return View();
        }

        [HttpPost]
        public ActionResult Create(Plan plan)
        {
            if (ModelState.IsValid)
            {
                db.Plan.Add(plan);
                db.SaveChanges();
                return RedirectToAction("Index");
            }

            return View(plan);
        }

        // GET: Plans/Edit/5
        public ActionResult Edit(int? id)
        {
            if (id == null)
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            var plan = db.Plan.Find(id);
            if (plan == null)
                return HttpNotFound();
            return View(plan);
        }

        // POST: Plans/Edit/5
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit([Bind(Include = "Id,Nazwa")] Plan plan)
        {
            if (ModelState.IsValid)
            {
                db.Entry(plan).State = EntityState.Modified;
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            return View(plan);
        }

        // GET: Plans/Delete/5
        public ActionResult Delete(int? id)
        {
            if (id == null)
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            var plan = db.Plan.Find(id);
            if (plan == null)
                return HttpNotFound();
            return View(plan);
        }

        // POST: Plans/Delete/5
        [HttpPost]
        [ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteConfirmed(int id)
        {
            var plan = db.Plan.Find(id);
            db.Plan.Remove(plan);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
                db.Dispose();
            base.Dispose(disposing);
        }
    }
}

EDIT2 使用表单创建视图的代码:

@model Lesson_plan.DAL.Plan

@using (Html.BeginForm("Create", "Plans"))
{
    <div>
        @Html.LabelFor(plan => plan.Name)<br/>
        @Html.TextAreaFor(plan => plan.Name)
    </div>
    <table style="border: 1px solid black; margin: 40px; width: 100%;">
        <tr>
            <th>Hours</th>
            <th>Monday</th>
            <th>Tuesday</th>
            <th>Wednesday</th>
            <th>Thursday</th>
            <th>Friday</th>
            <th>Saturday</th>
            <th>Sunday</th>
        </tr>
            @{
                for (int i = 0; i < 7; i++)
                {
                    <tr>  
                        //what sould i put here ?                    
                        <td><textarea></textarea></td>
                        <th><textarea></textarea></th>
                        <th><textarea></textarea></th>
                        <th><textarea></textarea></th>
                        <th><textarea></textarea></th>
                        <th><textarea></textarea></th>
                        <th><textarea></textarea></th>
                        <th><textarea></textarea></th>
                    </tr>
                }
            }
    </table>
    <p>
        <a type="button" class="btn btn-info" href=@Url.Action("Index")>Back</a>
        <input type="submit" value="Create"/>
    </p>
}

2 个答案:

答案 0 :(得分:3)

最好的方法是设计一个ViewModel类,它可以保存您的表单上需要提交的所有数据,包括计划和/或主题。

在接收此ViewModel的Action Method中,您可以分离数据,并根据该数据执行将数据存储在数据库中所需的任何插入和/或更新。

只有Controller应该知道您的数据库类。 ViewModel和Database对象之间的所有映射都应该由控制器完成,View不应该受到打扰或妨碍。

答案 1 :(得分:0)

通过将多个模型组合到视图模型中,可以将多个模型发送到视图。但是,你的问题似乎有所不同,所以这里有很长的答案:

至于数据库设计问题,我假设您正在使用关系存储,并且一个主题可以存在于多个计划中,因此应该有多对多应用程序。您可以阅读有关主题here的更多信息。

对于您的网络应用,您通常只需创建一个包含所需模型的ViewModel。如果您没有详细说明您的问题,那将是正确的答案。但是,在您的情况下,您的两个“模型”类已经链接,因此您的模型可以只是一个计划。

由于我假设您正在使用EF6(根据您生成的课程),您的计划主题将与计划一起发布。

我要做的是使用singleton在应用程序的某个位置缓存当前存在的主题,然后在回发时,您应该遍历计划的缓存主题,检查它们是否已存在于您的数据库中。如果他们不这样做 - 先插入它们,如果他们这样做 - 只需将它们添加到计划中的ICollection中。那你应该知道如何使用EF插入计划。

在此过程中可能会有更多的障碍,但你可以提出有关这些问题的新问题 - 你现在的问题太宽泛了。

我正在努力帮助你获得一些有用的东西,尽管它可能并不理想。一旦你开始工作,我建议阅读在哪里放置业务逻辑(以及如何保持你的控制器小)。 This文章可能是一个好的开始。

我建议的另一件事是将您的数据访问保留在单独的层中。 Goodle“3层架构”并在存储库模式上检查this video

祝你好运!

**发布OP-edit **

好的,看看你的代码似乎有很多问题,你可能想要分成多个问题。这是一个开始:

  1. 您的视图中没有任何表单,您需要在视图上添加表单和帖子按钮,并在标有Controller的{​​{1}}上显示操作方法的版本。对于旧版本,我建议使用asp {mcc核心的this教程和this。如果您想要“编辑”和“显示”视图的不同页面,只需创建单独的页面,但在创建时,您将需要一个表单。
  2. 目前,您应该将Plan用作viewModel。通常这不是理想的,但要解释为什么我需要写一本书作为答案。链接的资源应该有助于您了解该部分。
  3. 您似乎使用的是旧版本的asp.net mvc(也许我错了?请告诉我们哪一个)。如果您想在客户端的特定日期添加新主题,您还必须使用javascript(jQuery) - 或完整的客户端库,如React或Angular。如果您现在还不熟悉完整框架,请坚持使用JQuery。检查此question and answer以了解如何实现这一目标。
  4. 您可能希望将API方法和普通的旧MVC方法分离到不同的项目中。
  5. **编辑2 ** 现在看到您的计划创建代码,您似乎已经正确地读到[Post]是创建可以发布到服务器的输入的方式。

    但是,您只是将它用于您的计划名称。

    不使用下面的textarea(我假设这些是主题名称),而是使用类似

    的内容
    @Html.TextAreaFor(plan => plan.Name)

    假设您作为模型传递给视图的计划有任何主题,这将是列出它们并使其可编辑的方式。

    现在,您似乎希望根据星期几将它们分开,因此您可能需要进行一些过滤,例如:

    @for(int i = 0; i < plan.Subject.Count(); i++)
    {
        @Html.TextAreaFor(plan => plan.Subject[i].Name)
    }
    

    将其粘贴到七列中的每一列中。现在,这将为已经存在的每个主题创建textareas。

    至于在视图上动态创建新的,请参阅上面的第3点。如果你还没有任何科目,可以在你的数据库中创建一些假的,这样你就可以在客户端渲染一些并查看它们的源代码,然后按照我在#3中链接的文章。