2013-10-02 5 views
3

На моей странице индекса У меня есть форма поиска, которая позволяет пользователям извлекать информацию на основе 3 критериев поиска. Когда результаты поиска возвращаются с контроллера, они возвращаются как объект List, который является свойством модели представления и отображается в таблице под формой поиска.View Model posting null properties back to controller

Затем пользователь может выбрать, какие записи они хотели бы изменить. Они сделают это, установив флажок рядом с указанными записями. Затем, используя форму, которая появляется под полем поиска, введите новые значения и нажмите кнопку «Обновить», чтобы сохранить изменения. (мы делаем это, чтобы позволить пользователю делать массовые обновления без необходимости изменять таблицу подряд)

Вот скриншот, иллюстрирующий, что я имею в виду. Это то, что страница будет выглядеть после того, как пользователь нажал на кнопку «Поиск»:

enter image description here

Когда Хитом пользователя «Поиск» форма предписывается размещать обратно в индексный метод контроллера. Когда пользователь нажимает «Clone Selected Items», форма получает указание вернуться к методу «Обновить» в том же контроллере. Однако проблема заключается в том, что объект модели представления, который отправляется обратно к методу «Обновить», является полностью нулевым, за исключением значений, помещенных в текстовые поля New Territory, New Description и New Effective Date.

Я относительно новичок в ASP MVC, поэтому любая помощь/предложения будут оценены. Не уверен, почему View Model вернет сообщение с контроллера с теми же значениями, которые были отправлены туда при использовании кнопки «Поиск», но не сделает этого, используя «Clone Selected Items».

View Model (это то, что будет размещена на контроллер)

public class ZipCodeIndex 
{ 
    public List<ZipCodeTerritory> zipCodeTerritory { get; set; } 
    [DisplayName("Zip Code")] 
    public string searchZip { get; set; } 
    [DisplayName("Effective on this date")] 
    public string searchDate { get; set; } 
    [DisplayName("State")] 
    public string searchState { get; set; } 
    [DisplayName("New Territory")] 
    public string newTerritory { get; set; } 
    [DisplayName("New Description")] 
    public string newDescription { get; set; } 
    [DisplayName("New Effective Date")] 
    public string newEffectiveDate { get; set; } 

    public ZipCodeIndex() 
    { 
     zipCodeTerritory = new List<ZipCodeTerritory>(); 
    } 
} 

Модель (Это заполнит объект List в виде модели)

[MetadataType(typeof(ZipCodeTerritoryMetaData))] 
public partial class ZipCodeTerritory 
{ 
    public bool Update { get; set; } 
} 

public partial class ZipCodeTerritory 
{ 
    public string ChannelCode { get; set; } 
    public string DrmTerrDesc { get; set; } 
    public string IndDistrnId { get; set; } 
    public string StateCode { get; set; } 
    public string ZipCode { get; set; } 
    public System.DateTime EndDate { get; set; } 
    public System.DateTime EffectiveDate { get; set; } 
    public string LastUpdateId { get; set; } 
    public Nullable<System.DateTime> LastUpdateDate { get; set; } 
    public int Id { get; set; } 
} 

Вид

@model Monet.ViewModel.ZipCodeIndex 

    @using(Html.BeginForm("Index", "ZipCodeTerritory", FormMethod.Post)) 
    { 
     <div id="searchBox" class="boxMe"> 
      <div id="zipBox"> 
       @Html.Raw("Zip Code") 
       @Html.TextAreaFor(model => model.searchZip, new { style = "width: 300px;", placeholder = "Enter up to 35 comma separated zip codes" }) 
      </div> 
      <div id="dateBox"> 
       @Html.LabelFor(model => model.searchDate) 
       @Html.TextBoxFor(model => model.searchDate, new { style="width: 80px;"}) 
      </div> 
      <div id="stateBox"> 
       @Html.LabelFor(model => model.searchState) 
       @Html.TextBoxFor(model => model.searchState, new { style = "width: 25px;" }) 
       <button type="submit">Search</button> 
      </div> 
     </div> 
     <div id="errorStatus"> 
      @ViewBag.ErrorMessage    
     </div> 
     <div style="clear: both;"></div> 
    } 

<br/> 
@Html.ActionLink("Create New", "Create") 
<br/> 

@if (Model != null) 
{ 
    using(Html.BeginForm("Update", "ZipCodeTerritory", FormMethod.Post)) 
    { 
     <div id="cloneBox"> 
      @Html.LabelFor(model => model.newTerritory) 
      @Html.TextBoxFor(model => model.newTerritory, new { style="width: 30px;padding-left:10px;"}) 
      @Html.LabelFor(model => model.newDescription) 
      @Html.TextBoxFor(model => model.newDescription, new { style = "width: 250px;padding-left:10px;" }) 
      @Html.LabelFor(model => model.newEffectiveDate)  
      @Html.TextBoxFor(model => model.newEffectiveDate, new { style = "width: 80px;padding-left:10px;" }) 
      <button type="submit">Clone Selected Items</button>      
     </div> 
    }  

    <table id="thetable" class="tablesorter" > 
     <thead> 
      <th></th> 
      <th>Channel</th> 
      <th>Territory</th> 
      <th>Description</th> 
      <th>State</th> 
      <th>Zip</th> 
      <th>Effective</th> 
      <th>End Date</th> 
      <th>Last Update By</th> 
      <th>Last Update Date</th> 
      <th></th> 
     </thead> 
     <tbody> 
      @foreach (var item in Model.zipCodeTerritory) 
      { 
       <tr> 
        <td>@Html.CheckBoxFor(model => item.Update)</td> 
        <td> 
         @Html.DisplayFor(model => item.ChannelCode) 
        </td> 
        <td> 
         @Html.DisplayFor(model => item.IndDistrnId) 
        </td> 
        <td> 
         @Html.DisplayFor(model => item.DrmTerrDesc) 
        </td> 
        <td> 
         @Html.DisplayFor(model => item.StateCode) 
        </td> 
        <td> 
         @Html.DisplayFor(model => item.ZipCode) 
        </td> 
        <td> 
         @Html.DisplayFor(model => item.EffectiveDate) 
        </td> 
        <td> 
         @Html.DisplayFor(model => item.EndDate) 
        </td> 
        <td> 
         @Html.DisplayFor(model => item.LastUpdateId) 
        </td> 
        <td> 
         @Html.DisplayFor(model => item.LastUpdateDate) 
        </td> 
        <td> 
         @Html.ActionLink("Edit", "Edit", new { id = item.Id }) 
        </td> 
       </tr> 
      } 
     </tbody> 
    </table>  
} 

Контроллер

public ViewResult Index(ZipCodeIndex search) 
    { 
     try 
     { 
      //If search criteria is null page is loading for the first time so send blank view 
      if (String.IsNullOrWhiteSpace(search.searchZip) && 
       String.IsNullOrWhiteSpace(search.searchDate) && 
       String.IsNullOrWhiteSpace(search.searchState)) 
      { 
       return View(); 
      } 

      //Determine if necessary search criteria has been sent 
      if (String.IsNullOrWhiteSpace(search.searchZip) && String.IsNullOrWhiteSpace(search.searchState)) 
      { 
       ViewBag.ErrorMessage = "Either State or Zip Code Must be Specified"; 
       return View(search); 
      } 

      DateTime effectiveDate; 

      //Convert date string to DateTime type 
      if (String.IsNullOrWhiteSpace(search.searchDate)) 
      { 
       effectiveDate = DateTime.MinValue; 
      } 
      else 
      { 
       effectiveDate = Convert.ToDateTime(search.searchDate); 
      } 

      //Conduct search by State Code/Date alone 
      if (String.IsNullOrWhiteSpace(search.searchZip)) 
      { 
       search.zipCodeTerritory = (from z in db.ZipCodeTerritory 
              where z.StateCode.Equals(search.searchState) && 
               z.EffectiveDate >= effectiveDate 
              select z).ToList(); 
       return View(search); 
      } 

      //Zip codes have been requested to conduct zip search 
      string[] zipArray; 

      //Create array and remove white spaces 
      zipArray = search.searchZip.Split(',').Distinct().ToArray(); 
      for (int i = 0; i < zipArray.Length; i++) 
      { 
       zipArray[i] = zipArray[i].Trim(); 
      } 

      //Determine if state code is being used in search 
      if (String.IsNullOrWhiteSpace(search.searchState)) 
      { 
       foreach (var zip in zipArray) 
       { 
        var item = from z in db.ZipCodeTerritory 
           where z.ZipCode.Equals(zip) && 
             z.EffectiveDate >= effectiveDate 
           select z; 
        search.zipCodeTerritory.AddRange(item); 
       } 
      } 
      else 
      { 
       foreach (var zip in zipArray) 
       { 
        var item = from z in db.ZipCodeTerritory 
           where z.ZipCode.Equals(zip) && 
             z.EffectiveDate >= effectiveDate && 
             z.StateCode.Equals(search.searchState) 
           select z; 
        search.zipCodeTerritory.AddRange(item); 
       } 
      } 
     } 
     catch (DbEntityValidationException dbEx) 
     { 
      ViewBag.ErrorMessage = "An error has occurred, we apologize for the incovenience. IT has been notified and will resolve the issue shortly."; 
      SendEmail.ErrorMail(Common.ErrorCheck.CombineDbErrors(dbEx)); 
     } 
     catch (Exception ex) 
     { 
      ViewBag.ErrorMessage = ErrorCheck.FriendlyError(ex); 
      SendEmail.ErrorMail(ex); 
     } 

     return View(search); 
    } 


    [HttpPost] 
    public ActionResult Update(ZipCodeIndex updateZip) 
    { 
     foreach (var zipCode in updateZip.zipCodeTerritory) 
     { 
      if (zipCode.Update) 
      { 
       try 
       { 
        if (!string.IsNullOrEmpty(updateZip.newTerritory)) zipCode.IndDistrnId = updateZip.newTerritory; 
        if (!string.IsNullOrWhiteSpace(updateZip.newDescription)) zipCode.DrmTerrDesc = updateZip.newDescription; 
        if (!string.IsNullOrWhiteSpace(updateZip.newEffectiveDate)) zipCode.EffectiveDate = Convert.ToDateTime(updateZip.newEffectiveDate); 

        db.Entry(zipCode).State = EntityState.Modified; 
        db.SaveChanges(); 
       } 
       catch (DbEntityValidationException dbEx) 
       { 
        ViewBag.ErrorMessage = "An error has occurred, we apologize for the incovenience. IT has been notified and will resolve the issue shortly."; 
        SendEmail.ErrorMail(Common.ErrorCheck.CombineDbErrors(dbEx)); 
       } 
       catch (Exception ex) 
       { 
        ViewBag.ErrorMessage = "An error has occurred, we apologize for the incovenience. IT has been notified and will resolve the issue shortly."; 
        SendEmail.ErrorMail("Zip Code not updated: " + zipCode.ToString() + " |MESSAGE| " + ex.Message); 
       } 
      } 
     } 

     return RedirectToAction("Index", updateZip); 
    } 

EDIT

Я добавил следующие скрытые поля для второй формы (что сообщения в метод Update). Это вернет критерии поиска, однако объект List по-прежнему пуст.

@if (Model != null) 
{ 
    using(Html.BeginForm("Update", "ZipCodeTerritory", FormMethod.Post)) 
    { 
     @Html.HiddenFor(model => model.searchZip) 
     @Html.HiddenFor(model => model.searchDate) 
     @Html.HiddenFor(model => model.searchState) 
     @Html.HiddenFor(model => model.zipCodeTerritory) 

     <div id="cloneBox"> 
+0

Любые ошибки модели? – asawyer

+0

Это ваш Model.zipCodeTerritory, который не возвращается? –

+0

Нет, возвращается модель представления ZipCodeIndex. Я запомню это в сообщении, thx. – NealR

ответ

1

Ну, если добавление скрытого текста не сработало, я постараюсь сделать что-то вроде этого.

+0

Я все равно должен иметь возможность изменять логическое свойство элементов списка 'zipCodeTerritory'. – NealR

+0

Ya, который должен все еще быть в порядке, просто @ Html.CheckBoxFor (model => model [zipCodeTerritory [i] .update) –

+0

Это сработало, спасибо за вашу помощь! – NealR

-2

Я бы предложил попробовать использовать KnockoutJS, было бы гораздо легче размещать фактические данные с сервера обратно, только что обновил. Если вы хотите примеры - дайте мне знать, я буду рад дать некоторые.

Если это не вариант - Обратите внимание на то, что находится внутри созданной вами формы (BeginForm), потому что большая часть того, чего вы хотите, находится внутри, поэтому она не будет отправлена ​​на контроллер при записи.

+1

Кто-нибудь хочет прокомментировать, почему они были заблокированы? – NealR

+0

У него все еще была бы такая же проблема с knockoutJS – RiceRiceBaby

-1

Эта статья является неэффективным и неправильным способом устранения проблемы. ASP.NET MVC резервирует и использует слово «модель» в качестве ключевого слова во время процесса привязки модели. Вам нужно изменить имя «поиск» на «модель» в параметре результата действия. Это должно устранить вашу проблему с вашими поисковыми данными, не отправляя их обратно.

+0

Кто-нибудь хочет прокомментировать, почему они были приостановлены? – NealR

-1

Это ничего, но только когда вы возвращаете представление в действии в свой контроллер, создайте объект этой модели и передайте его только для просмотра.

+0

Кто-нибудь хочет прокомментировать, почему они были приостановлены? – NealR

-1

Перейти к RouteConfig.cs в App_start, то правильно, вы можете увидеть URL: {controller}/{action}/{id} в RegisterRoutes метод. Браузер отправится на этот маршрут. Имеет ли ваше действие «Редактировать действие» входной аргумент id? возможно, имя другое.

+2

Кто-нибудь хочет прокомментировать, почему они были заблокированы? – NealR

0

Когда мы используем метод Html Helper Html.DisplayFor(), он просто показывает данные как обычный текст. Вы можете проверить его на странице «Просмотр страницы» в своем браузере. Что вы делаете, так это использовать вспомогательный метод Html.HiddenFor для привязки данных, которые вам нужны после публикации. Или вы также можете связывать данные с помощью JQuery.Ajax

Смежные вопросы