MVC和实体框架中的嵌套查找

时间:2016-01-19 16:40:03

标签: c# asp.net-mvc entity-framework asp.net-mvc-4

我遇到了我正在处理的项目的问题。我对MVC比较陌生,所以我希望这很简单!

我试图对一个对象进行编辑,但是有问题的对象有一些它似乎无法绑定的ICollections。

我尝试更新的课程名为' Key',定义为:

public partial class Key
{
    public Key()
    {
        this.KeyFields = new HashSet<KeyField>();
        this.KeyServices = new HashSet<KeyService>();
    }

    public int ID { get; set; }
    public System.Guid APIKey { get; set; }
    public string SiteURL { get; set; }
    public bool Active { get; set; }
    public virtual ICollection<KeyField> KeyFields { get; set; }
    public virtual ICollection<KeyService> KeyServices { get; set; }
}

KeyField和KeyService类是:

public partial class KeyField
{
    public int ID { get; set; }
    public int SiteKey { get; set; }
    public int Field { get; set; }
    public bool Active { get; set; }

    public virtual Field Field1 { get; set; }
    public virtual Key Key { get; set; }
}

public partial class KeyService
{
    public int ID { get; set; }
    public int SiteKey { get; set; }
    public int Service { get; set; }
    public bool Active { get; set; }

    public virtual Key Key { get; set; }
    public virtual Service Service1 { get; set; }
}

相关的服务类是:

public partial class Service
{
    public Service()
    {
        this.KeyServices = new HashSet<KeyService>();
    }

    public int ID { get; set; }
    public string Name { get; set; }
    public int Service_View { get; set; }

    public virtual ICollection<KeyService> KeyServices { get; set; }
    public virtual View View { get; set; }

    [NotMapped]
    public bool IsSelected { get; set; }
}

和相关的Field类是:

public partial class Field
{
    public Field()
    {
        this.KeyFields = new HashSet<KeyField>();
    }

    public int ID { get; set; }
    public string Title { get; set; }
    public int Field_View { get; set; }

    public virtual View View { get; set; }
    public virtual ICollection<KeyField> KeyFields { get; set; }

    [NotMapped]
    public bool IsSelected { get; set; }
}

View正在使用名为&#39; KeyDetailsModel&#39;的自定义模型。它包含一个&#39; Key&#39;的实例。对象和2 IEnumebles。这些是我可以将数据库中的所有字段和服务输出到View上的复选框列表中。应在View上预选的字段和服务是Key类中的ICollections。 定义是:

public class KeyDetailsModel
{
    public Key Key { get; set; }
    public IEnumerable<Field> Fields { get; set; } 
    public IEnumerable<Service> Services { get; set; } 
}

控制器中的代码是设置&#39;显示&#39;页:

    public ViewResult KeyDetails(int id)
    {
        var fieldChannel = new Repo<Field>();
        var serviceChannel = new Repo<Service>();

        //gets the key information
        var key = _keyChannel.GetById(id);

        //gets all the fields in the database
        var fields = fieldChannel.GetAll();

        //gets all the services in the database
        var services = serviceChannel.GetAll();

        //gets the KeyFields for the key, and sets the IsSelected flag for the related Field
        foreach (var f in fields)
        {
            var selectedField = (from sf in key.KeyFields
                                 where sf.ID == f.ID && sf.SiteKey == id
                                 select sf).FirstOrDefault();

            if (selectedField != null)
            {
                f.IsSelected = true;
            }
        }

        //gets the KeyServices for the key, and sets the IsSelected flag for the related Service
        foreach (var f in services)
        {
            var selectedService = (from ss in key.KeyServices
                                 where ss.ID == f.ID && ss.SiteKey == id
                                 select ss).FirstOrDefault();

            if (selectedService != null)
            {
                f.IsSelected = true;
            }
        }

        //create the model
        var KeyDetailsModel = new KeyDetailsModel
        {
            Fields = fields,
            Key = key,
            Services = services
        };

        return View(KeyDetailsModel);
    }

这是控制器中执行编辑的方法:

    [HttpPost]
    public ActionResult KeyDetails(KeyDetailsModel KeyDetailsModel)
    {
        if (KeyDetailsModel != null && ModelState.IsValid)
        {
            return View(KeyDetailsModel);
        }
        else
        {
            return View(KeyDetailsModel);
        }
    }

最后,cshtml页面是:

@model EdinburghNapier.EAWebLayer.Admin.Models.KeyDetailsModel

@{
   ViewBag.Title = "KeyDetails";
   Layout = "~/Views/Shared/_Layout.cshtml";
 }

<h2>Key Details</h2>

@using (Html.BeginForm("KeyDetails", "Key", FormMethod.Post))
{
<fieldset>
    <legend>Key</legend>

    <div class="display-label">
        @Html.DisplayNameFor(model => model.Key.APIKey)
    </div>
    <div class="display-field">
        @Html.EditorFor(model => model.Key.APIKey)
    </div>

    <div class="display-label">
        @Html.DisplayNameFor(model => model.Key.SiteURL)
    </div>
    <div class="display-field">
        @Html.EditorFor(model => model.Key.SiteURL)
    </div>

    <div class="display-label">
        @Html.DisplayNameFor(model => model.Key.Active)
    </div>
    <div class="display-field">
        @Html.EditorFor(model => model.Key.Active)
    </div>


    <div class="display-field">
        <ul>
            @foreach (var f in Model.Fields)
            {
                <li>
                    <input type="checkbox"
                           name="Key.KeyFields" value="@f.ID" id="Field_@f.ID"
                           checked="@f.IsSelected"/>
                    <label for="@f.ID">@f.Title</label>
                </li>
            }
        </ul>
    </div>

    <div class="display-field">
        <ul>
            @foreach (var f in Model.Services)
            {
                <li>
                    <input type="checkbox"
                   name="Key.KeyServices" value="@f.ID" id="Service_@f.ID"
                   checked="@f.IsSelected"/>
                    <label for="@f.ID">@f.Name</label>
                </li>
            }
        </ul>
    </div>
</fieldset>    
@Html.HiddenFor(model => model.Key.ID)
<input type="submit" value="Save"/>
}

我提交表单时发生的事情是&#39; KeyFields&#39;和&#39; KeyServices&#39; &#39; Key&#39;的属性&#39; KeyDetailsModel&#39;中的类始终为0.编辑屏幕似乎无法将复选框列表绑定到属性。 这样做的一个结果是,当我提交时,ModelState的状态始终为false。

我已经把头撞在墙上几天了,希望有人可以帮忙!我很欣赏我可能提供了太多的代码和太少的解释 - 请告诉我,如果是这样的话!

1 个答案:

答案 0 :(得分:0)

您以不正确的方式绑定复选框,您应该阅读更多相关内容,您可以查看以下文章: http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/

您的代码应该更改,以便每个复选框的名称都包含一个索引器:

<div class="display-field">
    <ul>
        @for (var i = 0; i < Model.Fields.Count(); i++)
             {
            <li>
                <input type="checkbox"
                       name="@Html.NameFor(x=>x.Fields[i])" value="@Model.Fields[i].ID" id="@Html.IdFor(x=>x.Fields[i])"
                       checked="@Model.Fields[i].IsSelected" />
                <label for="@Html.NameFor(x=>x.Fields[i])">@Model.Fields[i].Title</label>
            </li>
        }
    </ul>
</div>

<div class="display-field">
    <ul>
        @for (var i = 0; i < Model.Services.Count(); i++)
                {
                <li>
                    <input type="checkbox"
                           name="@Html.NameFor(x=>x.Services[i])" value="@Model.Services[i].ID" id="@Html.IdFor(x=>x.Services[i])"
                           checked="@Model.Services[i].IsSelected" />
                    <label for="@Html.NameFor(x=>x.Services[i])">@Model.Services[i].Name</label>
                </li>
        }
    </ul>
</div>

您还必须在此处将“服务”和“字段”属性设为数组:

public class KeyDetailsModel
{
    public Key Key { get; set; }
    public Field[] Fields { get; set; } 
    public Service[] Services { get; set; } 
}

或者,您可以在周期内使用@Html.CheckBoxFor(x=>x.Fields[i].IsSelected,坚持使用Mvc Helpers,他们确实有所作为。