#c# #asp.net-core #razor-pages
#c# #asp.net-core #razor-страницы
Вопрос:
Привет, у меня есть родительско-дочерние отношения между двумя объектами — PositionSummary и PositionDetail.
Вот модели.
using System;
using System.Collections.Generic;
namespace ThePositionerRazor2.Models
{
public partial class Possummary
{
public Possummary()
{
Posdetail = new HashSet<Posdetail>();
}
public int PositionId { get; set; }
public string PositionNbr { get; set; }
public string WorkTitle { get; set; }
public string Purpose { get; set; }
public double? JobValue { get; set; }
public double? TimeTotal { get; set; }
public double? Fte { get; set; }
public double? Salary { get; set; }
public DateTime? Lastupdated { get; set; }
public string JobFamily { get; set; }
public int? DescriptionTypeId { get; set; }
public virtual Descriptiontype DescriptionType { get; set; }
public virtual ICollection<Posdetail> Posdetail { get; set; }
}
}
и
using System;
using System.Collections.Generic;
namespace ThePositionerRazor2.Models
{
public partial class Posdetail
{
public int PosdetailId { get; set; }
public int PositionId { get; set; }
public int Workitem { get; set; }
public int? TimeSpent { get; set; }
public int? ImportanceId { get; set; }
public double? TimeNrmz { get; set; }
public int? Knowdepth { get; set; }
public int? Need { get; set; }
public int? TimeCalc { get; set; }
public double? Postskval { get; set; }
public double? Ftetime { get; set; }
public double? Ftesal { get; set; }
public DateTime Lastupdated { get; set; }
public virtual Imp Importance { get; set; }
public virtual Knowdep KnowdepthNavigation { get; set; }
public virtual Possummary Position { get; set; }
public virtual Timescale TimeSpentNavigation { get; set; }
public virtual Workhier WorkitemNavigation { get; set; }
}
}
Родительский элемент успешно переходит к списку выбранных дочерних записей. На странице списка дочерних элементов я перехожу на дочернюю страницу создания с параметром (родительский внешний ключ), потому что я не хочу каждый раз вводить родительский внешний ключ.
Процедура создания страницы OnPostAsync возвращается на страницу дочернего списка после сохранения (т.Е. Стандартный код каркаса).
Мой код компилируется без ошибок. Когда я нажимаю кнопку создания страницы создания, запись сохраняет ее в базе данных SQL Server, НО переход обратно на страницу дочернего списка приводит к ошибке.
Ошибка: ArgumentOutOfRangeException: индекс был вне диапазона. Должно быть неотрицательным и меньше размера коллекции. (Параметр «индекс») ThePositionerRazor2.Pages.PositionDetail.Pages_PositionDetail_Index.ExecuteAsync() в Index.cshtml 14. Создать новую
Идея заключается в том, что при возврате в дочерний список возврат будет успешным, и если будет запрошено другое создание, родительский внешний ключ по умолчанию все еще будет действовать.
** Вопросы:
- Why am I getting the above error?
- How do I have the parent foreign key remain in effect between the list and the create pages upon repeated ‘create’ entries?
- Same question as 2- but returning repeatedly to create page with ‘back to list’ as way of navigating out?**
In general I am finding that creating of child records on a different razor page (standard scaffolding using entity framework) leaves a lot to be desired- quite cumbersome when the need to create child records prepopulating the parent foreign key would be a common scenario.
Thoughts?
Below are the cshtml files and cs files for the PositionSummary and PositionDetail
PositionSummary
@page
@model ThePositionerRazor2.Pages.PositionSummary.IndexModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-page="Create">Create New</a>
</p>
<div class="row">
<div class="col-md-12">
<div class="panel panel-primary list-panel" id="list-panel">
<div class="panel-heading list-panel-heading">
<h1 class="panel-title list-panel-title">Position Summary</h1>
</div>
<div class="panel-body">
<table id="Possum-data-table"
class="table table-striped table-bordered"
style="width:100%">
@*<table class="table">*@
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Possummary[0].PositionNbr)
</th>
<th>
@Html.DisplayNameFor(model => model.Possummary[0].WorkTitle)
</th>
<th>
@Html.DisplayNameFor(model => model.Possummary[0].Purpose)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Possummary)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.PositionNbr)
</td>
<td>
@Html.DisplayFor(modelItem => item.WorkTitle)
</td>
<td>
@Html.DisplayFor(modelItem => item.Purpose)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.PositionId">Edit</a> |
@*<a asp-page="./Details" asp-route-id="@item.PositionId">Details</a> |*@
<a asp-page="../PositionDetail/Index" asp-route-id="@item.PositionId">Position Details</a> |
<a asp-page="./Delete" asp-route-id="@item.PositionId">Delete</a>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
</div>
</div>
@section Scripts
{
<link href="https://cdn.datatables.net/1.10.15/css/dataTables.bootstrap.min.css" rel="stylesheet" />
<script src="https://cdn.datatables.net/1.10.15/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/1.10.15/js/dataTables.bootstrap4.min.js "></script>
<script type="text/javascript">
$(document).ready(function () {
$('#Possum-data-table').DataTable({ "order": [[0, "asc"]] });
});
</script>
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using ThePositionerRazor2.Models;
namespace ThePositionerRazor2.Pages.PositionSummary
{
public class IndexModel : PageModel
{
private readonly ThePositionerRazor2.Models.WorkManagerV4Context _context;
public IndexModel(ThePositionerRazor2.Models.WorkManagerV4Context context)
{
_context = context;
}
public IList<Possummary> Possummary { get;set; }
public async Task OnGetAsync()
{
Possummary = await _context.Possummary
.Include(p => p.DescriptionType).ToListAsync();
}
}
}
Индекс сведений о местоположении
@page
@model ThePositionerRazor2.Pages.PositionDetail.IndexModel
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-page="Create">Create New</a>
<a asp-page="/PositionDetail/Create" asp-route-PositionID="@Model.Posdetail[0].PositionId">Create New</a>
</p>
<form method="post">
<p>
Desired Position: @Html.TextBox("SelectedPosition")
</p>
<input type="submit" value="Search Positions" />
<div class="row">
<div class="col-md-12">
<div class="panel panel-primary list-panel" id="list-panel">
<div class="panel-heading list-panel-heading">
<h1 class="panel-title list-panel-title">Position Detail</h1>
</div>
<div class="panel-body">
<table id="posdet-data-table"
class="table table-striped table-bordered"
style="width:100%">
@*<table class="table">*@
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Posdetail[0].Position)
</th>
<th>
@Html.DisplayNameFor(model => model.Posdetail[0].WorkitemNavigation)
</th>
<th>
@Html.DisplayNameFor(model => model.Posdetail[0].TimeNrmz)
</th>
<th>
@Html.DisplayNameFor(model => model.Posdetail[0].Importance)
</th>
<th>
@Html.DisplayNameFor(model => model.Posdetail[0].Lastupdated)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Posdetail)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Position.PositionNbr)
</td>
<td>
@Html.DisplayFor(modelItem => item.WorkitemNavigation.Workitemid)
</td>
<td>
@Html.DisplayFor(modelItem => item.TimeNrmz)
</td>
<td>
@Html.DisplayFor(modelItem => item.Importance.ImportanceId)
</td>
<td>
@Html.DisplayFor(modelItem => item.Lastupdated)
</td>
<td>
<a asp-page="./Edit" asp-route-id="@item.PosdetailId">Edit</a> |
<a asp-page="./Details" asp-route-id="@item.PosdetailId">Details</a> |
<a asp-page="./Delete" asp-route-id="@item.PosdetailId">Delete</a>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
</div>
</div>
</form>
@section Scripts
{
<link href="https://cdn.datatables.net/1.10.15/css/dataTables.bootstrap.min.css" rel="stylesheet" />
<script src="https://cdn.datatables.net/1.10.15/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/1.10.15/js/dataTables.bootstrap4.min.js "></script>
<script type="text/javascript">
$(document).ready(function () {
$('#posdet-data-table').DataTable({ "order": [[0, "desc"]] });
});
</script>
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using ThePositionerRazor2.Models;
namespace ThePositionerRazor2.Pages.PositionDetail
{
public class IndexModel : PageModel
{
private readonly ThePositionerRazor2.Models.WorkManagerV4Context _context;
public IndexModel(ThePositionerRazor2.Models.WorkManagerV4Context context)
{
_context = context;
}
public IList<Posdetail> Posdetail { get;set; }
public async Task OnGetAsync(int? ID, string SelectedPosition)
{
if (ID != null)
{
Posdetail = await _context.Posdetail
.Include(p => p.Importance)
.Include(p => p.KnowdepthNavigation)
.Include(p => p.Position)
.Include(p => p.TimeSpentNavigation)
.Include(p => p.WorkitemNavigation)
.Where(p => p.Position.PositionId == ID)
.ToListAsync();
}
else
{
Posdetail = await _context.Posdetail
.Include(p => p.Importance)
.Include(p => p.KnowdepthNavigation)
.Include(p => p.Position)
.Include(p => p.TimeSpentNavigation)
.Include(p => p.WorkitemNavigation)
.Where(p => p.Position.PositionNbr == SelectedPosition)
.ToListAsync();
}
}
public async Task OnPostAsync(string SelectedPosition)
{
Posdetail = await _context.Posdetail
.Include(p => p.Importance)
.Include(p => p.KnowdepthNavigation)
.Include(p => p.Position)
.Include(p => p.TimeSpentNavigation)
.Include(p => p.WorkitemNavigation)
.Where(p => p.Position.PositionNbr == SelectedPosition)
.ToListAsync();
}
}
}
Сведения о позиции создают
@page
@model ThePositionerRazor2.Pages.PosDetailList.CreateModel
@{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>Posdetail</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="Posdetail.PositionId" class="control-label"></label>
<select asp-for="Posdetail.PositionId" class="form-control"
asp-items="ViewBag.PositionId">
</select>
</div>
<div class="form-group">
<label asp-for="Posdetail.Workitem" class="control-label"></label>
<select asp-for="Posdetail.Workitem" class ="form-control" asp-items="ViewBag.Workitem"></select>
</div>
<div class="form-group">
<label asp-for="Posdetail.TimeSpent" class="control-label"></label>
<select asp-for="Posdetail.TimeSpent" class ="form-control" asp-items="ViewBag.TimeSpent"></select>
</div>
<div class="form-group">
<label asp-for="Posdetail.ImportanceId" class="control-label"></label>
<select asp-for="Posdetail.ImportanceId" class ="form-control" asp-items="ViewBag.ImportanceId"></select>
</div>
<div class="form-group">
<label asp-for="Posdetail.TimeNrmz" class="control-label"></label>
<input asp-for="Posdetail.TimeNrmz" class="form-control" />
<span asp-validation-for="Posdetail.TimeNrmz" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Posdetail.Knowdepth" class="control-label"></label>
<select asp-for="Posdetail.Knowdepth" class ="form-control" asp-items="ViewBag.Knowdepth"></select>
</div>
<div class="form-group">
<label asp-for="Posdetail.Need" class="control-label"></label>
<input asp-for="Posdetail.Need" class="form-control" />
<span asp-validation-for="Posdetail.Need" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Posdetail.TimeCalc" class="control-label"></label>
<input asp-for="Posdetail.TimeCalc" class="form-control" />
<span asp-validation-for="Posdetail.TimeCalc" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Posdetail.Postskval" class="control-label"></label>
<input asp-for="Posdetail.Postskval" class="form-control" />
<span asp-validation-for="Posdetail.Postskval" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Posdetail.Ftetime" class="control-label"></label>
<input asp-for="Posdetail.Ftetime" class="form-control" />
<span asp-validation-for="Posdetail.Ftetime" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Posdetail.Ftesal" class="control-label"></label>
<input asp-for="Posdetail.Ftesal" class="form-control" />
<span asp-validation-for="Posdetail.Ftesal" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Posdetail.Lastupdated" class="control-label"></label>
<input asp-for="Posdetail.Lastupdated" class="form-control" />
<span asp-validation-for="Posdetail.Lastupdated" class="text-danger"></span>
</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");}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using ThePositionerRazor2.Models;
namespace ThePositionerRazor2.Pages.PosDetailList
{
public class CreateModel : PageModel
{
private readonly ThePositionerRazor2.Models.WorkManagerV4Context _context;
public CreateModel(ThePositionerRazor2.Models.WorkManagerV4Context context)
{
_context = context;
}
public IActionResult OnGet(int PositionID)
{
int ID = 5;
ViewData["ImportanceId"] = new SelectList(_context.Imp, "ImportanceId", "ImportanceId");
ViewData["Knowdepth"] = new SelectList(_context.Knowdep, "DepthId", "DepthId");
ViewData["PositionId"] = new SelectList(_context.Possummary, "PositionId", "PositionNbr", PositionID);
ViewData["TimeSpent"] = new SelectList(_context.Timescale, "TimevalId", "TimevalId");
ViewData["Workitem"] = new SelectList(_context.Workhier, "Workitemid", "Workitemid");
return Page();
}
[BindProperty]
public Posdetail Posdetail { get; set; }
// To protect from overposting attacks, 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.Posdetail.Add(Posdetail);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
}
Ответ №1:
возврат к странице списка дочерних элементов приводит к ошибке
Исключение ArgumentOutOfRangeException: индекс был вне диапазона. Должно быть неотрицательным и меньше размера коллекции. (Параметр «индекс»)
Чтобы исправить ошибку, вы можете попытаться передать выбранное PositionId
значение через маршрут на индексную страницу, изменив код, как показано ниже.
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Posdetail.Add(Posdetail);
await _context.SaveChangesAsync();
var positionId = Posdetail.PositionId;
return RedirectToPage("./Index", new { ID = positionId });
}