.Net Core Razor страница с несколькими раскрывающимися списками для одной и той же сущности - PullRequest
1 голос
/ 26 октября 2019

Можно ли каким-либо образом иметь несколько раскрывающихся меню, отображающих данные из одной и той же сущности базы данных на одной и той же странице бритвы, не создавая несколько классов с новыми идентификаторами (например, ResourceID; ResourceID1; ResourceID2)

IЯ могу отобразить раскрывающийся список с соответствующими данными из базы данных MS SQL на страницах бритвы «Create.cshtml» и «Edit.cshtml», но выбранные данные при сохранении отображают идентификатор выбранного ресурса вместо имениресурс в представлениях «Index.cshtml», «Detail.cshtml» и «Delete.cshtml».

Модель ресурса:

namespace ProjectReporting.Models
{
    public class Resource
    {
        public int ID { get; set; }

        [Display(Name = "First Name")]
        public string FirstName { get; set; }

        [Display(Name = "Last Name")]
        public string LastName { get; set; }

        [Display(Name = "Long Name")]
        public string LongName { get; set; }

        [DefaultValue(true)]
        [Display(Name = "Active")]
        public bool IsActive { get; set; } = true;

        [Display(Name = "Is Manager")]
        public bool IsManager { get; set; }

        [Display(Name = "Is Forecast Owner")]
        public bool IsForecastOwner { get; set; }

        public ICollection<Project> Projects { get; set; }

    }
}

Модель проекта:

namespace ProjectReporting.Models
{
    public class Project
    {
        public int ID { get; set; }

        [Display(Name = "ID")]
        public int PID { get; set; }

        [Display(Name = "Project Name")]
        public string ProjectName { get; set; }

        [Display(Name = "Forecast Owner")]
        public int ResourceID { get; set; }
        public Resource Resource { get; set; }

        [Display(Name = "DSM")]
        public int? ResourceID1 { get; set; }

        public ICollection<ProjectComment> ProjectComments { get; set; }

    }
}

Страница Create.cshtml:

@page
@model ProjectReporting.Pages.Projects.CreateModel

@{
    ViewData["Title"] = "Create";
}

<h1>Create</h1>

<h4>Project</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form method="post">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="Project.PID" class="control-label"></label>
                <input asp-for="Project.PID" class="form-control" />
                <span asp-validation-for="Project.PID" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Project.ProjectName" class="control-label"></label>
                <input asp-for="Project.ProjectName" class="form-control" />
                <span asp-validation-for="Project.ProjectName" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Project.ResourceID" class="control-label"></label>
                <select asp-for="Project.ResourceID" class="form-control" asp-items="ViewBag.ResourceID"><option value="" default="" selected="">-- Select --</option></select>
            </div>
            <div class="form-group">
                <label asp-for="Project.ResourceID1" class="control-label"></label>
                <select asp-for="Project.ResourceID1" class="form-control" asp-items="ViewBag.ResourceID1"><option value="" default="" selected="">-- Select --</option></select>
            </div>
            <div class="form-group form-check">
                <label class="form-check-label">
                    <input class="form-check-input" asp-for="Project.IsArchived" /> @Html.DisplayNameFor(model => model.Project.IsArchived)
                </label>
            </div>
            <div class="form-group">
                <input type="submit" value="Create" class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>

<div>
    <a asp-page="Index">Back to List</a>
</div>

@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

Страница Create.cshtml:

namespace ProjectReporting.Pages.Projects
{
    public class CreateModel : PageModel
    {
        private readonly ProjectReporting.Data.ApplicationDbContext _context;

        public CreateModel(ProjectReporting.Data.ApplicationDbContext context)
        {
            _context = context;
        }

        public IActionResult OnGet()
        {
            ViewData["OrganisationID"] = new             SelectList(_context.ProjectType.Where(a => a.IsActive == true), "ID", "TypeName");
            ViewData["ResourceID"] = new SelectList(_context.Resource.Where(a => a.IsActive & a.IsForecastOwner == true), "ID", "LongName");
            ViewData["ResourceID1"] = new SelectList(_context.Resource.Where(a => a.IsActive == true), "ID", "LongName");
            return Page();
        }

        [BindProperty]
        public Project Project { get; set; }

        // To protect from overposting attacks, please enable the specific properties you want to bind to, for
        // more details see https://aka.ms/RazorPagesCRUD.
        public async Task<IActionResult> OnPostAsync()
        {
            if (!ModelState.IsValid)
            {
                return Page();
            }

            _context.Project.Add(Project);
            await _context.SaveChangesAsync();

            return RedirectToPage("./Index");
        }
    }
}

Страница Index.cshtml:

@page
@model ProjectReporting.Pages.Projects.IndexModel

@{
    ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
    <a asp-page="Create">Create New</a>
</p>
<table class="table">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.Project[0].PID)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Project[0].Organisation)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Project[0].ProjectName)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Project[0].Resource)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Project[0].ResourceID1)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Project[0].IsArchived)
            </th>
            <th></th>
        </tr>
    </thead>
    <tbody>
@foreach (var item in Model.Project) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.PID)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Organisation.OrgName)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.ProjectName)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Resource.LongName)
            </td>
            <td>
                @Html.DisplayFor(modelItem => c)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.IsArchived)
            </td>
            <td>
                <a asp-page="./Edit" asp-route-id="@item.ID">Edit</a> |
                <a asp-page="./Details" asp-route-id="@item.ID">Details</a> |
                <a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
            </td>
        </tr>
}
    </tbody>
</table>

Item.Resource.LongName отлично работает для первого ресурса, но я бы хотел, чтобы то же самое произошло с item.Resource.LongName.

Index.cshtml.cs

namespace ProjectReporting.Pages.Projects
{
    public class IndexModel : PageModel
    {
        private readonly ProjectReporting.Data.ApplicationDbContext _context;

        public IndexModel(ProjectReporting.Data.ApplicationDbContext context)
        {
            _context = context;
        }

        public IList<Project> Project { get;set; }

        public async Task OnGetAsync()
        {
            Project = await _context.Project
                .Include(p => p.Resource).ToListAsync();
        }
    }
}

Я установил FK в файле миграции для создания базы данныхиметь возможность извлекать данные и не создавать один файл класса по ресурсам.

table.ForeignKey(
     name: "FK_Project_Resource_ResourceID",
     column: x => x.ResourceID,
     principalTable: "Resource",
     principalColumn: "ID",
     onDelete: ReferentialAction.Restrict);
table.ForeignKey(
     name: "FK_Project_Resource_ResourceID1",
     column: x => x.ResourceID1,
     principalTable: "Resource",
     principalColumn: "ID",
     onDelete: ReferentialAction.Restrict);

В результате отображаются правильные данные в раскрывающемся списке и правильный идентификатор ресурса, выбранный при сохранении. Тем не менее, индекс, подробности и страница удаления отображают только ResourceID вместо LongName. Если я использую Resource.LongName для второго ResourceID1, он по праву отображает тот же LongName, что и для ResourceID.

Как я могу иметь несколько раскрывающихся списков ресурсов на странице, которые указывают на одну и ту же сущность и отображать LongName наИндекс, детализация и удаление страниц?

1 Ответ

0 голосов
/ 28 октября 2019

Неясно, какие у вас отношения между Resource и Project, и вы не можете использовать оба значения ResourceID и ResourceID1 для свойства Resource для восстановления различных ресурсов.

Дляотношения «многие ко многим», вы можете сослаться на

https://docs.microsoft.com/en-us/ef/core/modeling/relationships#many-to-many

Обходной путь заключается в том, что вы просто получаете все ресурсы в обработчике и извлекаете его в поле зрения:

Индекс.cshtml.cs:

public class IndexModel : PageModel
{
    private readonly ProjectReporting.Data.ApplicationDbContext _context;

    public IndexModel(ProjectReporting.Data.ApplicationDbContext context)
    {
        _context = context;
    }

    public IList<Project> Project { get;set; }
    public IList<Resource> Resources { get; set; }

    public async Task OnGetAsync()
    {
        Resources = await _context.Resource.ToListAsync();
        Project = await _context.Projects
            .Include(p => p.Resource).ToListAsync();
    }
}

Index.cshtml:

<td>
    @Html.DisplayFor(modelItem => item.Resource.LongName)
</td>
<td>
    @{ 
        var resource = Model.Resources.FirstOrDefault(r => r.ID == item.ResourceID1);
    }
    @resource.LongName
</td>
...