2016-01-19 3 views
0

У меня проблема с проектом, над которым я работаю. Я относительно новичок в MVC, поэтому я надеюсь, что это что-то простое!Вложенный поиск в MVC и Entity Framework

Я пытаюсь выполнить редактирование объекта, но объект, о котором идет речь, имеет пару 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; } 
} 

и соответствующий класс поле:

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 использует пользовательскую модель под названием «KeyDetailsModel». Он содержит экземпляр объекта «Key» и 2 IEnumerables. Они существуют, поэтому я могу выводить все поля и службы в базе данных в список флажков в представлении. Поля и сервисы, которые должны быть предварительно выбраны в представлении, являются ICollections в классе Key. это определение:

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="[email protected]" 
          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="[email protected]" 
        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"/> 
} 

Что происходит, когда я отправляю форму, так это то, что свойства «KeyFields» и «KeyServices» класса «Key» в «KeyDetailsModel» всегда равны 0. Экран редактирования, похоже, не может связывать проверку в списки. Одним из следствий этого является то, что статус ModelState всегда является ложным при отправке.

Я уже несколько дней бил головой о стену, надеясь, что кто-то может помочь! Я ценю, что я, возможно, поставил слишком много кода и слишком мало объяснений - пожалуйста, дайте мне знать, если это так!

+0

В дополнение к использованию цикла 'for' в соответствии с ответом raderick лучший подход заключается в использовании' EditorTemplate' для моделей вашей коллекции. См. [Этот ответ] (http://stackoverflow.com/questions/30363177/mvc-action-isnt-triggered-in-controller/30363319#30363319) для примера. И код contriller ужасно неэффективен - вызов базы данных на каждой итерации каждого цикла –

ответ

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, они действительно имеют значение.