简体   繁体   中英

Viewing data from another model results in DynamicProxies object being shown

I am currently working on a help desk system and writing up a view to view all tickets for a user.

A ticket consists of parent data like ticket category, open user, technician, etc. and then there is the child with ticketNotes. The first ticket note (that is added upon initial creation) is the ticket description. In the table of tickets on my view I would like to show just this one note (the ticket description) for each ticket. Here is my controller:

public ActionResult Index()
{

    var model = from t in db.Tickets
                join tn in db.TicketNotes on t.TicketId equals tn.TicketId
                where t.OpenUserId == new Guid("00000000-0000-0000-0000-000000000000")
                orderby t.OpenDate
                select t;

    return View(model);
}

My ViewModel:

namespace HelpDesk.WebUI.ViewModel
{
    public class UserTickets
    {
        public int TicketNumber { get; set; }

        public Guid CategoryId { get; set; }

        public virtual Category Category { get; set; }

        public Guid OpenUserId { get; set; }

        public virtual User OpenUser { get; set; }

        public DateTime OpenDate { get; set; }

        public Guid TechnicianId { get; set; }

        public virtual User Technician { get; set; }

        public Guid TicketStatusId { get; set; }

        public virtual TicketStatus TicketStatus { get; set; }

        public Nullable<DateTime> CloseDate { get; set; }

        public string Note { get; set; }

    }
}

My Models:

namespace HelpDesk.Model
{
    public class Ticket
    {
        public Ticket()
        {
            this.TicketNotes = new HashSet<TicketNote>();
        }
        public Guid TicketId { get; set; }

        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        [Required]
        public int TicketNumber { get; set; }

        [ForeignKey("Category")]
        [Required]
        public Guid CategoryId { get; set; }

        public virtual Category Category { get; set; }

        [ForeignKey("OpenUser")]
        [Required]
        public Guid OpenUserId { get; set; }

        public virtual User OpenUser { get; set; }

        [DataType(DataType.Date)]
        [Required]
        public DateTime OpenDate { get; set; }

        [ForeignKey("Technician")]
        [Required]
        public Guid TechnicianId { get; set; }

        public virtual User Technician { get; set; }

        [ForeignKey("TicketStatus")]
        [Required]
        public Guid TicketStatusId { get; set; }

        public virtual TicketStatus TicketStatus { get; set; }

        [DataType(DataType.Date)]
        public Nullable<DateTime> CloseDate { get; set; }

        public virtual ICollection<TicketNote> TicketNotes { get; set; }
        //public virtual ICollection<TicketSubscription> TicketSubscriptions { get; set; }
    }
}

namespace HelpDesk.Model
{
    public class TicketNote
    {
        public Guid TicketNoteId { get; set; }

        [ForeignKey("Ticket")]
        [Required]
        public Guid TicketId { get; set; }

        public virtual Ticket Ticket { get; set; }

        public string Note { get; set; }
        [Display(Name = "Attachment")]
        public string AttachmentPath { get; set; }

        [MaxLength(255)]
        public string AttachmentName { get; set; }

        [ForeignKey("UserNote")]
        [Required]
        public Guid UserNoteId { get; set; }

        public virtual User UserNote { get; set; }

        [DataType(DataType.Date)]
        [Required]
        public DateTime TicketNoteDate { get; set; }

        [Display(Name = "Private Note")]
        [Required]
        public bool PublicFlag { get; set; }

        public bool Delete { get; set; }

    }
}

And here is my view:

@model IEnumerable<HelpDesk.Model.Ticket>

@{

        ViewBag.Title = "Index";
    }

    <h2>Index</h2>

    <p>
        @Html.ActionLink("Create New", "Create")
    </p>
    <table class="table">
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.Category.CategoryName)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.OpenUser.FullName)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Technician.FullName)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.TicketStatus.StatusDescription)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.TicketNumber)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.OpenDate)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.CloseDate)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.TicketNotes)
            </th>
            <th></th>
        </tr>

    @foreach (var item in Model) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.Category.CategoryName)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.OpenUser.NTUserName)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Technician.NTUserName)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.TicketStatus.StatusDescription)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.TicketNumber)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.OpenDate)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.CloseDate)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.TicketNotes.OrderBy(t=t.TicketId).First().TicketText)
            </td>
            <td>
                @Html.ActionLink("Edit", "Edit", new { id=item.TicketId }) |
                @Html.ActionLink("Details", "Details", new { id=item.TicketId }) |
            </td>
        </tr>
    }

    </table>

Everything works except for the ticket note which is pulling from the TicketNote Model. For that field I am getting

System.Data.Entity.DynamicProxies.Ticket_BA0BCDE55BCBE6BA2FE66FAD697C8D2C0D7AAD7C5F797406642720CB57DA2A89

As suggested by one I changed the code in my controller to be:

public ActionResult Index()
    {

        var model = db.Tickets
                    .Include(t=>t.TicketNotes)
                    .Where(t.OpenUserId == new Guid("00000000-0000-0000-0000-000000000000"))
                    .OrderBy(t => t.OpenDate);

        return View(model);
    }

and my view as suggested but I am getting an error on this line in the view:

@Html.DisplayFor(modelItem => item.TicketNotes.OrderBy(t=t.TicketId).First().TicketText)

It is saying the 'The name 't' does not exist in the current context.

(optionally) Use this in your controller for better performance as it will eagerly load your TicketNotes instead of lazily load them:

public ActionResult Index()
{

    var model = db.Tickets
                  .Include(t=>t.TicketNotes)
                  .Where(t.OpenUserId == new Guid("00000000-0000-0000-0000-000000000000"))
                  .OrderBy(t=>t.OpenDate);

    return View(model);
}

And use this in your view (which will work with both eager and lazy loaded notes):

@Html.DisplayFor(modelItem => item.TicketNotes.OrderBy(t=t.TicketId).First().TicketText)

It seems that you are using LazyLoading with your entity model, thus the actual type of the data is not your Ticket , but some datatype dynamically generated by EntityFramework, that handles actual loading details.

You can:

  1. Either disable the LazyLoading so that Ticket stays to be Ticket . But in such a case you will have to load all related entities manually .
  2. Or manually render desired partial views(display templates) .

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