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

本文关键字:嵌套 查找 框架 实体 MVC | 更新日期: 2023-09-27 18:31:05

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

我正在尝试对一个对象执行编辑,但有问题的对象有几个似乎无法绑定的 ICollection。

我尝试更新的类称为"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; }
}

相关的字段类是:

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; }
}

视图使用的是名为"KeyDetailsModel"的自定义模型。它包含"键"对象的一个实例和 2 个 IEnumerable。这些字段和服务的存在是为了我可以将数据库中的所有字段和服务输出到视图上的复选框列表中。应在"视图"上预先选择的字段和服务是"键"类中的 ICollect。定义是:

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

这是控制器中设置"显示"页面的代码:

    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"/>
}

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

几天来我一直在用

头撞墙,希望有人能帮忙!我很感激我可能提供了太多的代码和太少的解释 - 如果是这种情况,请告诉我!

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

您以

不正确的方式绑定了复选框,您应该阅读更多关于它的信息,您可以检查以下文章: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 助手,它们确实会有所作为。