将项添加到嵌套集合

时间:2015-11-16 05:56:00

标签: model-view-controller nested parent-child one-to-many

我按照下面的两个帖子进行操作但是无法让它工作: http://www.itorian.com/2013/04/nested-collection-models-in-mvc-to-add.htmlAdding more items to nested collections in MVC?

我可以编辑和删除,但我无法使用“编辑”表单向产品添加其他常见问题解答。感谢有人可以帮助我。

我有2个型号 - 产品和常见问题解答我可以根据需要为产品添加尽可能多的常见问题。

public class Product
{
    public Product()
    {
        this.Faqs = new HashSet<Faq>();
        this.Overviews = new HashSet<Overview>();
    }
    public int ProductId { get; set; }
    public string ProductName { get; set; }
    public virtual ICollection<Faq> Faqs { get; set; }
}

public class Faq
{
    public int FaqId { get; set; }
    public string FaqQuestion { get; set; }
    public string FaqAnswer { get; set; }
    [NotMapped]
    public Nullable<bool> DeleteFaq { get; set; }
    public int ProductId { get; set; }
    public virtual Product Product { get; set; }
}

我在View / Product / EditorTemplates / Faq.cshtml中创建了一个编辑模板:

@model xyz.Models.Faq
@using xyz.Helpers;

@{ Layout = null; }

@using (Html.BeginCollectionItem("Faqs"))
{ 
<div class="Faq">
@Html.HiddenFor(model => model.FaqId)
@Html.HiddenFor(model => model.ProductId)
    <div class="col-lg-12">
        @Html.LabelFor(model => model.FaqQuestion, htmlAttributes: new { @class = "control-label" })
    </div>
    <div class="col-lg-12">
        @Html.EditorFor(model => model.FaqQuestion, new { htmlAttributes = new { @class = "form-control" } })
    </div>

    <div class="col-lg-12">
        @Html.LabelFor(model => model.FaqAnswer, htmlAttributes: new { @class = "control-label" })
    </div>
    <div class="col-lg-12">
        @Html.EditorFor(model => model.FaqAnswer, new { htmlAttributes = new { @class = "form-control" } })
    </div>

    @Html.HiddenFor(model => model.DeleteFaq, new { @class = "mark-for-delete" })
    @Html.RemoveLink("Remove", "div.Faq", "input.mark-for-delete")

}

这是我的Edit.cshtml页面:

@model xyz.Models.Product 
@using xyz.Helpers

@{
ViewBag.Title = "Edit";
}

<h2>Edit</h2>

@using (Html.BeginForm("Edit", "product", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
@Html.AntiForgeryToken()

<div class="form-horizontal">
    <h4>Product</h4>
    <hr />
    @Html.ValidationSummary(true, "", new { @class = "text-danger" })
    @Html.HiddenFor(model => model.ProductId)

    <div class="form-group">
        <div id="faqs">
            @Html.LabelFor(model => model.Faqs, "Faq", new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Faqs)
            </div>
        </div>
    </div>

    <p>
@Html.AddLink("Add More Faqs", "#faqs", ".ProductId", ".Faq", "Faqs", typeof(eqinsurance.Models.Faq), Convert.ToString(Model.ProductId))
    </p>

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

我在Helpers / HtmlHelpers.cs中创建了一个HTML Helper,如下所示:

namespace xyz.Helpers
{
public static class HtmlHelpers
{
    public static IHtmlString RemoveLink(this HtmlHelper htmlHelper, string linkText, string container, string deleteElement)
    {
        var js = string.Format("javascript:removeNestedForm(this,'{0}','{1}');return false;", container, deleteElement);
        TagBuilder tb = new TagBuilder("a");
        tb.Attributes.Add("href", "#");
        tb.Attributes.Add("onclick", js);
        tb.InnerHtml = linkText;
        var tag = tb.ToString(TagRenderMode.Normal);
        return MvcHtmlString.Create(tag);
    }

            public static IHtmlString AddLink<TModel>(this HtmlHelper<TModel> htmlHelper, string linkText, string containerElement, string parentId, string counterElement, string collectionProperty, Type nestedType, string buttonId)
    {
        var ticks = DateTime.UtcNow.Ticks;
        var nestedObject = Activator.CreateInstance(nestedType);
        var partial = htmlHelper.EditorFor(x => nestedObject).ToHtmlString().JsEncode();
        partial = partial.Replace("id=\\\"nestedObject", "id=\\\"" + collectionProperty + "_" + ticks + "_");
        partial = partial.Replace("name=\\\"nestedObject", "name=\\\"" + collectionProperty + "[" + ticks + "]");
        partial = partial.Replace(parentId + "\\\" type=\\\"hidden\\\" value=\\\"0", parentId + "\\\" type=\\\"hidden\\\" value=\\\"" + buttonId);
        var js = string.Format("javascript:addNestedForm('{0}','{1}','{2}','{3}');return false;", containerElement, counterElement, ticks, partial);
        TagBuilder tb = new TagBuilder("a");
        tb.Attributes.Add("href", "#");
        tb.Attributes.Add("onclick", js);
        tb.InnerHtml = linkText;
        var tag = tb.ToString(TagRenderMode.Normal);
        return MvcHtmlString.Create(tag);
    }

    private static string JsEncode(this string s)
    {
        if (string.IsNullOrEmpty(s)) return "";
        int i;
        int len = s.Length;
        StringBuilder sb = new StringBuilder(len + 4);
        string t;
        for (i = 0; i < len; i += 1)
        {
            char c = s[i];
            switch (c)
            {
                case '>':
                case '"':
                case '\\':
                    sb.Append('\\');
                    sb.Append(c);
                    break;
                case '\b':
                    sb.Append("\\b");
                    break;
                case '\t':
                    sb.Append("\\t");
                    break;
                case '\n':
                    break;
                case '\f':
                    sb.Append("\\f");
                    break;
                case '\r':
                    break;
                default:
                    if (c < ' ')
                    {
                        string tmp = new string(c, 1);
                        t = "000" + int.Parse(tmp, System.Globalization.NumberStyles.HexNumber);
                        sb.Append("\\u" + t.Substring(t.Length - 4));
                    }
                    else
                    {
                        sb.Append(c);
                    }
                    break;
            }
        }
        return sb.ToString();
    }
}
}

我有一个CustomJs.js文件,我也包含在App_start / BundleConfig.cs中:

function removeNestedForm(element, container, deleteElement) {
$container = $(element).parents(container);
$container.find(deleteElement).val('True');
$container.hide();
}

function addNestedForm(container, counter, ticks, content) {
var nextIndex = $(counter).length;
var pattern = new RegExp(ticks, "gi");
content = content.replace(pattern, nextIndex);
$(container).append(content);
}

这是我在ProductController中的编辑方法:

    // GET: Product/Edit/5
    public ActionResult Edit(int? id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }

        Product product = db.Product.Find(id);
        if (product == null)
        {
            return HttpNotFound();
        }

        return View(product);
    }

    // POST: Product/Edit/5
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Edit(Product product)
    {
        if (ModelState.IsValid)
        {
            foreach (var item in product.Faqs)
            {
                if (item.DeleteFaq == true)
                {
                    db.Entry(item).State = EntityState.Deleted;
                }
                else if (item.FaqId == 0)
                {
                    db.Entry(item).State = EntityState.Added;
                }
               else
                {
                    db.Entry(item).State = EntityState.Modified;
                }
                db.SaveChanges();
            }

            db.Entry(product).State = EntityState.Modified;
            db.SaveChanges();

          return RedirectToAction("Details", new { id = product.ProductId });
        }

0 个答案:

没有答案