我正在用Asp建立一个Bug跟踪器。在网上学习自定进度的在线课程。我遇到了"对象未设置为引用错误"同时试图列出分配给每个项目的门票在我的项目详细信息视图。我知道信息没有传递进去,但我不知道如何解决这个问题。对这个问题有什么具体的解决办法吗?
尝试绕过:
- 注释出票状态和票优先级代码,它工作,但它没有显示我想要的一切。
Youtube Video of Error
错误截图
GitHub Repo中的高亮代码
问题代码:
@model TheBugTrackerProject.Models.Project
@using TheBugTrackerProject.Models.Enums
@using TheBugTrackerProject.Services.Interfaces
@using Microsoft.AspNetCore.Identity
@using TheBugTrackerProject.Models
@inject UserManager<BTUser> userManager
@inject IBTProjectService ProjectService
@inject IBTHistoryService HistoryService
@{
ViewData["Title"] = "Details";
BTUser btUser = await userManager.GetUserAsync(User);
BTUser projectManager = await ProjectService.GetProjectManagerAsync(Model.Id);
}
<h1>Details</h1>
<div>
<div class="container-fluid">
<div class="row gy-2">
<div class="col-md-12 col">
<div class="row col-cols-2 mt-5 bg-secondary">
<div class="card col m-1 p-2">
<div class="body">
@* Project Name *@
<h5>@Model.Name</h5>
@* Project Description *@
<p>@Model.Description</p>
<div class="progress-container progress-info m-b-25">
<span class="progress-badge" style="font-size:small">Project Status</span>
<div class="progress">
@* Razor code block *@
@{
var start = Model.StartDate.DateTime;
var end = Model.EndDate.DateTime;
var today = DateTime.Now;
var percent = today >= end ? 100 : today < start ? 0 : Math.Round((today.Subtract(start)) / (end.Subtract(start)) * 100);
}
<div class="progress-bar" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" style="width: @percent;">
@* Use Progress Bar code variable here *@
<span class="progress-value">@percent%</span>
</div>
</div>
</div>
</div>
</div>
<div class="card col m-1 p-2">
<div class="body">
<ul class=" list-unstyled basic-list">
<li>Start Date: <span class="">@Model.StartDate.ToString("dd MMM, yyyy")</span></li>
<li>Deadline: <span class="">@Model.EndDate.ToString("dd MMM, yyyy")</span></li>
<li>Priority: <span class="">@Model.ProjectPriority?.Name</span></li>
@* if() logic *@
@if (today < end && today >= start)
{
<li>Status:<span class="">Active</span></li>
}
else
{
<li>Status:<span class="">Inactive</span></li>
}
</ul>
</div>
</div>
</div>
</div>
<div class="col-md-4 col mt-5 ">
<div class="bg-secondary">
<div class="card m-1 p-2">
<div class="header">
<h2>Project Manager</h2>
<hr />
</div>
<div class="body" style="overflow-y:auto;height:300px;">
@* if() logic for Avatar/Default etc *@
@if (projectManager != null)
{
<div>
@if (projectManager.AvatarFileData != null)
{
<img class="rounded-circle" src="data:image/*;base64, @(Convert.ToBase64String(projectManager.AvatarFileData))" alt="" />
}
else
{
<img class="rounded-circle " style="width: 60px; height:60px;" src="https://cdn.icon-icons.com/icons2/1378/PNG/512/avatardefault_92824.png" alt="" />
}
<div>
<h5>@projectManager.FullName</h5>
<span>@projectManager.Email</span>
<p class="text-muted m-b-0">Project Manager</p>
@if (User.IsInRole(nameof(Roles.Admin)) || (btUser.Id == projectManager.Id))
{
<a class="btn btn-xs alert-primary" style="font:small;" asp-action="AssignUsers" asp-controller="Projects" asp-route-id="@Model.Id">Manage Team</a>
}
</div>
</div>
}
else
{
<div>
<img class="rounded-circle" style="width:60px;height:60px;" src="https://cdn.icon-icons.com/icons2/1378/PNG/avatardefault_92824.png" />
<div class="wid-u-info">
<h5 class="text-muted m-b-0">Not Assigned</h5>
@if (User.IsInRole(nameof(Roles.Admin)))
{
<span><a asp-action="AssignProjectManager" asp-controller="Home" asp-route-id="@Model.Id" class="btn btn-xs btn-outline-info">Assign PM</a></span>
}
<span><a asp-action="AssignProjectManager" asp-controller="Home" asp-route-id="@Model.Id" class="btn btn-xs btn-outline-info">Assign PM</a></span>
</div>
</div>
}
</div>
</div>
</div>
</div>
<div class="col-md-4 col mt-5 ">
<div class="bg-secondary">
<div class="card m-1 p-2">
<div class="header">
<h2>Project Team</h2>
<hr />
</div>
<div class="body" style="overflow-y:auto;height:300px;">
<ul class="right_chat list-unstyled mb-0">
@* Logic for avatars *@
@foreach (BTUser member in await ProjectService.GetAllProjectMembersExceptPMAsync(Model.Id))
{
<li class="">
<a href="">
<div class="media">
@if (member.AvatarFileData != null)
{
<img class="" src="data:image/*;base64,@(Convert.ToBase64String(member.AvatarFileData))" alt="" />
}
else
{
<img class="" src="https://cdn.icon-icons.com/icons2/1378/PNG/avatardefault_92824.png" />
}
<div class="">
<span class="">@member.FullName</span>
<span class="">@((await userManager.GetRolesAsync(member)).FirstOrDefault())</span>
</div>
</div>
</a>
</li>
}
</ul>
</div>
</div>
</div>
</div>
<div class="col-md-4 col mt-5 ">
<div class="bg-dark">
<div class="card m-1 p-2">
<div class="header">
<h2>Project Activity</h2>
<hr />
</div>
<div class="body" style="overflow-y:auto;height:300px;background-color:antiquewhite">
@* Project Activity loop *@
@foreach (TicketHistory history in await HistoryService.GetProjectTicketHistoryAsync(Model.Id, btUser.CompanyId.Value))
{
<div class="">
<span class="date">@history.Created.ToString("dd MM, yyyy")</span>
<h6>@history.Description</h6>
<span>By: <a href="" title="@history.User.FullName">@history.User.FullName</a></span>
<div class="">
<p>The Ticket <b>@history.Property</b> was edited</p>
<p>@($"Previous {history.Property}: {history.OldValue}")</p>
<p>@($"Current {history.Property}: {history.NewValue}")</p>
<div class="media">
<div class="media-body">
<h6 class="mb-0"></h6>
</div>
</div>
</div>
</div>
}
</div>
</div>
</div>
</div>
<div class="col-md-12 col">
<div class="mt-5 bg-secondary">
<div class="card m-1 p-2">
<div class="header">
<h2>Tickets</h2>
</div>
<div class="body">
<div class="table-responsive" style="overflow-y:auto;height:600px;">
<table class="table table-hover">
<thead class="">
<tr>
@* Table header *@
<th>Title</th>
<th>Developer</th>
<th>Status</th>
<th>Priority</th>
<th>Date</th>
<th>Action</th>
</tr>
</thead>
<tbody>
@* Table body *@
@foreach (var ticket in Model.Tickets.OrderByDescending(d => d.Created))
{
<tr>
<td><a asp-action="Details" asp-controller="Tickets" asp-route-id="@ticket.Id" style="color:black"><strong>@ticket.Title</strong></a> </td>
<td>
@if (ticket.DeveloperUserId != null)
{
@ticket.DeveloperUser?.FullName
}
else
{
if (User.IsInRole(nameof(Roles.Admin)) || User.IsInRole(nameof(Roles.ProjectManager)))
{
<a class="btn btn-xs btn-info" asp-action="AssignDeveloper" asp-controller="Home" asp-route-ticketId="@ticket.Id">Assign Dev</a>
}
}
</td>
@if (ticket.TicketStatus.Name == "New")
{
<td><span class="badge-success">@ticket.TicketStatus.Name</span></td>
}
else
{
<td><span class="badge-success">@ticket.TicketStatus.Name </span></td>
}
<td><span class="badge-warning">@ticket.TicketPriority.Name </span></td>
<td>@ticket.Created.ToString("MM-dd-yyyy")</td>
<td>
<a class="btn btn-sm btn-outline-info" asp-action="Details" asp-controller="Tickets" asp-route-id="@ticket.Id"><i class="fs-5 bi-justify"></i></a>
@if (ticket.DeveloperUserId == btUser.Id || ticket.OwnerUserId == btUser.Id || (projectManager?.Id == btUser.Id) || User.IsInRole(nameof(Roles.Admin)))
{
<a class="btn btn-sm btn-outline-secondary" asp-action="Edit" asp-controller="Tickets" asp-route-id="@ticket.Id"><i class="fs-5 bi-pencil"></i></a>
}
@if (User.IsInRole("Admin") || (projectManager?.Id == btUser.Id))
{
<a class="btn btn-sm btn-outline-danger"><i class="fs-5 bi-archive"></i></a>
}
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
谢谢。
注:我的代码一团糟;但我很期待在这里和将来与其他人合作。
在您的项目服务中,您没有Include
-ing票据状态,因此它将为空。试试这样做:
Project project = await _context.Projects
.Include(p => p.Tickets)
.ThenInclude(t => t.TicketStatus) // <-- add this line
.Include(p => p.Members)
.Include(p => p.ProjectPriority)
.FirstOrDefaultAsync(p => p.Id == projectId && p.CompanyId == companyId);