简体   繁体   中英

MVC two models same view model IEnumerable issue

I am trying to learn MVC and came up with a little project to figure it out. I have two models:

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace reqcoll.Models
{
  public class Project
  {

    [Key]
    public int ProjectID { get; set; }

   [Required]
   [DataType(DataType.Text)]
   [MaxLength(150, ErrorMessage = "The project name cannot be longer than 150 characters!")]
   [Display(Name = "Project name:")]
   public string projectName { get; set; }

   [Required]
   [Display(Name = "Project type:")]
   public ProjectType projectType { get; set; }

   public int RequirementID { get; set; }
   public virtual List<Requirement> Requirements { get; set; }

  }
}

and

using System.ComponentModel.DataAnnotations;

namespace reqcoll.Models
{
  public class Requirement
  {
    [Key]
    public int requirementID { get; set; }

    [DataType(DataType.Text)]
    [MaxLength(150, ErrorMessage = "This is a short description, it cannot be longer than 150 characters.")]
    [Required]
    public string shortDesc { get; set; }

    [DataType(DataType.Text)]
    [MaxLength(3999, ErrorMessage = "This is a short description, it cannot be longer than 150 characters.")]
    [Required]
    public string longDesc { get; set; }

    [Required]
    public int priorityCode { get; set; }

    [Required]
    public int OrderID { get; set; }

    public int projectID { get; set; }

  }
}

And I have one view:

@using reqcoll.Models;
@model Tuple<Project, IEnumerable<Requirement> >



@{
  ViewBag.Title = "ReqColl - project";
}

<div class="top-spacing col-md-12 col-lg-12 col-sm-12">
  <div class=" well">
    @Html.ValidationSummary(true)
    <div class="row">
      @Html.LabelFor(tuple => tuple.Item1.projectName, htmlAttributes: new {     @class = "control-label col-md-2 col-lg-2 col-sm-12" })
      <div class="col-md-10 col-lg-10 col-sm-12">
        @Html.TextBoxFor(tuple => tuple.Item1.projectName, htmlAttributes: new {     @class = "ProjectNameInput" })
        @Html.ValidationMessageFor(tuple => tuple.Item1.projectName)
      </div>
    </div>
    @Html.ValidationSummary(true)
    <div class="row row-spacing">
      @Html.LabelFor(tuple => tuple.Item1.projectType, htmlAttributes: new {     @class = "control-label col-md-2 col-lg-2 col-sm-12" })
      <div class="col-md-10 col-lg-10 col-sm-12">
        @Html.DropDownListFor(tuple => tuple.Item1.projectType, new SelectList(
                  new List<Object>{
                       new { value = 0 , text = "...Select..."  },
                       new { value = 1 , text = "Windows application"  },
                       new { value = 2 , text = "Web application" },
                       new { value = 3 , text = "Device application"}
                    },
                  "value",
                  "text",
                   0), htmlAttributes: new { @class = "DropDownList" })
        @Html.ValidationMessageFor(tuple => tuple.Item1.projectType)
      </div>
    </div>
  </div>
</div>

<div class="top-spacing col-md-6 col-lg-6 col-sm-12">
  <div class=" well">
    <table class="table">
      <tr>
        <th>
          @Html.DisplayNameFor(tuple => tuple.Item2.shortDesc)
        </th>
        <th></th>
      </tr>

      @foreach (Requirement item in (IEnumerable<Requirement>)Model.Item2)
      {
        <tr>
          <td>
            @Html.DisplayFor(modelItem => item.shortDesc)
          </td>
          <td>
            @Html.ActionLink("E", "Edit", new { id = item.requirementID }) |
            @Html.ActionLink("D", "Delete", new { id = item.requirementID })
           </td>
        </tr>
      }

    </table>


  </div>
</div>

<div class="top-spacing col-md-6 col-lg-6 col-sm-12">
  <div class=" well">



  </div>
</div>

When I run the website, I get an error:

CS1061: 'IEnumerable' does not contain a definition for 'shortDesc' and no extension method 'shortDesc' accepting a first argument of type 'IEnumerable' could be found (are you missing a using directive or an assembly reference?)

The error is in the view on the line "@Html.DisplayNameFor(tuple => tuple.Item2.shortDesc)"

For some reason it doesn't see the property "shortDesc" in Item2. I can't figure out why not.

Any help is appreciated.

The problem you are facing is that tuple.Item2 is a collection, so there is no tuple.Item2.shortDesc as you declared.

You need to do something like:

@Html.DisplayFor(tuple => tuple.Item2)

Then you will need a Display Template that will know what to render with that collection passed in.

This question has been asked before, this will lead you to the right path:

ASP.net MVC - Display Template for a collection

The Item2 property points to IEnumerable<Requirement> as indicated in the model

@model Tuple<Project, IEnumerable<Requirement>>

I can see that you already enumerate Item2 in this code

@foreach (Requirement item in (IEnumerable<Requirement>)Model.Item2)

and you already make a call to item.shortDesc. Is this a duplicate call?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM