asp.net mvc 父子视图,父视图更新子视图 [英] asp.net mvc parent child view with parent view updating children

查看:32
本文介绍了asp.net mvc 父子视图,父视图更新子视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用局部视图来创建父子视图.我最喜欢的是父视图上的提交按钮来保存子值.

我有以下模型.

公开课课程{公共 int CourseId { 获取;放;}公共字符串名称 { 获取;放;}公共 int Par { 得到;放;}公共字符串 Tee { get;放;}公共十进制评级{得到;放;}公共虚拟 IEnumerable孔{得到;放;}公共静态课程创建(){var course = new Course();course.Par = 72;varholes = new List();for (int i = 0; i <18; i++){holes.Add(new CourseHole() { Course = course, Number = i + 1, Par = 4 });}course.Holes = 洞;回程;}}公开课课程洞{公共 int CourseHoleId { 获取;放;}public int Number { 得到;放;}公共 int Par { 得到;放;}公共 int 长度 { 得到;放;}公共 int 排名 { 得到;放;}公共课程课程{得到;放;}}

以及以下父视图.

@model Golf_Statz.Models.Course@{ViewBag.Title = "创建";}<h2>创建</h2>@using (Html.BeginForm()){@Html.AntiForgeryToken()<div class="form-horizo​​ntal"><h4>课程</h4><小时/>@Html.ValidationSummary(true, "", new { @class = "text-danger" })<div class="form-group">@Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })<div class="col-md-4">@Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })@Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })

@Html.LabelFor(model => model.Par, htmlAttributes: new { @class = "control-label col-md-2" })<div class="col-md-4">@Html.EditorFor(model => model.Par, new { htmlAttributes = new { @class = "form-control" } })@Html.ValidationMessageFor(model => model.Par, "", new { @class = "text-danger" })

<div class="form-group">@Html.LabelFor(model => model.Tee, htmlAttributes: new { @class = "control-label col-md-2" })<div class="col-md-4">@Html.EditorFor(model => model.Tee, new { htmlAttributes = new { @class = "form-control" } })@Html.ValidationMessageFor(model => model.Tee, "", new { @class = "text-danger" })

@Html.LabelFor(model => model.Rating, htmlAttributes: new { @class = "control-label col-md-2" })<div class="col-md-4">@Html.EditorFor(model => model.Rating, new { htmlAttributes = new { @class = "form-control" } })@Html.ValidationMessageFor(model => model.Rating, "", new { @class = "text-danger" })

@foreach(Model.Holes 中的Golf_Statz.Models.CourseHole 洞){@Html.Partial("CreateHole", 洞)}<div class="form-group"><div class="col-md-offset-2 col-md-10"><input type="submit" value="Create" class="btn btn-default"/>

}<div>@Html.ActionLink("返回列表", "索引")

@section 脚本 {@Scripts.Render("~/bundles/jqueryval")}

以及下面的局部视图.

@model Golf_Statz.Models.CourseHole@{ViewBag.Title = "创建洞";}@using (Html.BeginForm()){@Html.AntiForgeryToken()<div class="form-horizo​​ntal" id="CreateHole-" + model.CourseHoleId>@Html.ValidationSummary(true, "", new { @class = "text-danger" })<div class="form-group"><div class="col-md-2 col-md-offset-2"><p>@Model.Number</p>

<div class="col-md-2">@Html.EditorFor(model => model.Par, new { htmlAttributes = new { @class = "form-control" } })@Html.ValidationMessageFor(model => model.Par, "", new { @class = "text-danger" })

<div class="col-md-2">@Html.EditorFor(model => model.Length, new { htmlAttributes = new { @class = "form-control" } })@Html.ValidationMessageFor(model => model.Length, "", new { @class = "text-danger" })

<div class="col-md-2">@Html.EditorFor(model => model.Ranking, new { htmlAttributes = new { @class = "form-control" } })@Html.ValidationMessageFor(model => model.Ranking, "", new { @class = "text-danger" })

}@section 脚本 {@Scripts.Render("~/bundles/jqueryval")}

我的控制器方法是.

//GET:课程/创建公共 ActionResult 创建(){返回视图(Course.Create());}//POST:课程/创建//为了防止过度发布攻击,请启用您要绑定的特定属性,例如//更多详细信息,请参见 http://go.microsoft.com/fwlink/?LinkId=317598.[HttpPost][验证AntiForgeryToken]public ActionResult Create([Bind(Include = "CourseId,Name,Par,Tee,Rating")] 课程课程){如果(模型状态.IsValid){db.Courses.Add(课程);foreach (var 孔在 course.Holes){db.CourseHoles.Add(hole);}db.SaveChanges();return RedirectToAction("索引");}返回视图(课程);}

无论我似乎做什么课程.HttpPost Create 方法中的漏洞始终为空.我想我想要类似于 这个 但它用于编辑,我想要它用于创建.任何帮助将不胜感激,因为这是我的第一个 mvc 项目.

解决方案

您的 foreach 循环正在生成重复的 id 属性(无效的 html)和 name 与您的模型无关的属性.将部分更改为 EditorTemplate

/Views/Shared/EditorTemplates/CourseHole.cshtml

并删除BeginFormAntiForgeryToken 和脚本

@model Golf_Statz.Models.CourseHole<div class="form-horizo​​ntal" id="CreateHole-" + model.CourseHoleId><div class="form-group"><div class="col-md-2 col-md-offset-2"><p>@Model.Number</p>

<div class="col-md-2">@Html.EditorFor(model => model.Par, new { htmlAttributes = new { @class = "form-control" } })@Html.ValidationMessageFor(model => model.Par, "", new { @class = "text-danger" })

<div class="col-md-2">@Html.EditorFor(model => model.Length, new { htmlAttributes = new { @class = "form-control" } })@Html.ValidationMessageFor(model => model.Length, "", new { @class = "text-danger" })

<div class="col-md-2">@Html.EditorFor(model => model.Ranking, new { htmlAttributes = new { @class = "form-control" } })@Html.ValidationMessageFor(model => model.Ranking, "", new { @class = "text-danger" })

然后在主视图中

@Html.EditorFor(m => m.Holes)

EditorFor() 方法将正确生成用于绑定到集合的 html,例如

<input name="Holes[1].Par" ...>

您还需要删除 [Bind] 属性,因为您排除了属性 Holes,而且您似乎无论如何都想绑定到所有属性.

旁注:您不会为孔 CourseHoleIdNumber 属性生成输入,因此这些不会回传.

I am using a partial view to create a parent child view. What I would ideally like is the submit button on the parent view to save the child values.

I have the following model.

public class Course
{
    public int CourseId { get; set; }
    public string Name { get; set; }
    public int Par { get; set; }
    public string Tee { get; set; }
    public decimal Rating { get; set; }
    public virtual IEnumerable<CourseHole> Holes { get; set; }

    public static Course Create()
    {
        var course = new Course();
        course.Par = 72;
        var holes = new List<CourseHole>();
        for (int i = 0; i < 18; i++)
        {
            holes.Add(new CourseHole() { Course = course, Number = i + 1, Par = 4 });
        }
        course.Holes = holes;
        return course;
    }
}

public class CourseHole
{
    public int CourseHoleId { get; set; }
    public int Number { get; set; }
    public int Par { get; set; }
    public int Length { get; set; }
    public int Ranking { get; set; }
    public Course Course { get; set; }
}

And the following parent view.

@model Golf_Statz.Models.Course

@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>


@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>Course</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-4">
                @Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
            </div>

            @Html.LabelFor(model => model.Par, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-4">
                @Html.EditorFor(model => model.Par, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Par, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Tee, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-4">
                @Html.EditorFor(model => model.Tee, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Tee, "", new { @class = "text-danger" })
            </div>

            @Html.LabelFor(model => model.Rating, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-4">
                @Html.EditorFor(model => model.Rating, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Rating, "", new { @class = "text-danger" })
            </div>
        </div>

        @foreach (Golf_Statz.Models.CourseHole hole in Model.Holes)
        {
            @Html.Partial("CreateHole", hole)
        }

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
}



<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

And the following partial view.

@model Golf_Statz.Models.CourseHole

@{
    ViewBag.Title = "CreateHole";
}

@using (Html.BeginForm()) 
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal" id="CreateHole-" + model.CourseHoleId>
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            <div class="col-md-2 col-md-offset-2">
                <p>@Model.Number</p>
            </div>
            <div class="col-md-2">
                @Html.EditorFor(model => model.Par, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Par, "", new { @class = "text-danger" })
            </div>
            <div class="col-md-2">
                @Html.EditorFor(model => model.Length, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Length, "", new { @class = "text-danger" })
            </div>
            <div class="col-md-2">
                @Html.EditorFor(model => model.Ranking, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Ranking, "", new { @class = "text-danger" })
            </div>
        </div>
    </div>
}

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

My controller methods are.

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

        // POST: Course/Create
        // 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 Create([Bind(Include = "CourseId,Name,Par,Tee,Rating")] Course course)
        {
            if (ModelState.IsValid)
            {
                db.Courses.Add(course);
                foreach (var hole in course.Holes)
                {
                    db.CourseHoles.Add(hole);
                }
                db.SaveChanges();
                return RedirectToAction("Index");
            }

            return View(course);
        }

No matter what I seem to do course.Holes in the HttpPost Create method is always null. I think I want something similar to this but it's for editing and I want it for creating. Any help would be greatly appreciated as this is my first mvc project.

解决方案

Your foreach loop is generating duplicate id attributes (invalid html) and name attributes which have no relationship to your model. Change the partial to an EditorTemplate

/Views/Shared/EditorTemplates/CourseHole.cshtml

and remove the BeginForm, AntiForgeryToken and scripts

@model Golf_Statz.Models.CourseHole
<div class="form-horizontal" id="CreateHole-" + model.CourseHoleId>
    <div class="form-group">
        <div class="col-md-2 col-md-offset-2">
            <p>@Model.Number</p>
        </div>
        <div class="col-md-2">
            @Html.EditorFor(model => model.Par, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.Par, "", new { @class = "text-danger" })
        </div>
        <div class="col-md-2">
            @Html.EditorFor(model => model.Length, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.Length, "", new { @class = "text-danger" })
        </div>
        <div class="col-md-2">
            @Html.EditorFor(model => model.Ranking, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.Ranking, "", new { @class = "text-danger" })
        </div>
    </div>
</div>

and then in the main view

@Html.EditorFor(m => m.Holes)

The EditorFor() method will correctly generate the html for binding to a collection, for example

<input name="Holes[0].Par" ...>
<input name="Holes[1].Par" ...>

You also need to remove the [Bind] attribute since you are excluding property Holes, and you seem to want to bind to all properties anyway.

Side note: You do not generate an input for the hole CourseHoleId or Number properties so these wont post back.

这篇关于asp.net mvc 父子视图,父视图更新子视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
C#/.NET最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆