Coming from ASP.NET WebForms and feeling a bit overwhelmed. I have an ASP.NET Core Razor Page that loads an incident and all the comments related to that incident. I figured out how to refresh the comments with a partial Razor Page and AJAX, but also want to add a new comment with AJAX and refresh the comments.
Models:
public class Incident
{
public Incident()
{
Comments = new HashSet<Comment>();
}
public int Id { get; set; }
public string Title { get; set; }
public virtual ICollection<Comment> Comments { get; set; }
}
public class Comment
{
public int IncidentId { get; set; }
public int Id { get; set; }
public string CommentText { get; set; }
public virtual Incident Incident { get; set; }
}
Incident.cshtml:
@page
@model MyNamespace.IncidentModel
@{
ViewData["Title"] = "Emergency Operations Center";
}
<h4>@Html.DisplayFor(model => model.Incident.Title)</h4>
@Html.HiddenFor(model => model.Incident.Id)
<hr />
<form method="post" data-ajax="true" data-ajax-method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="row">
<input type="hidden" asp-for="Incident.Id" />
<div class="col form-group">
<label asp-for="NewComment.CommentText" class="control-label"></label>
<input asp-for="NewComment.CommentText" class="form-control" />
<span asp-validation-for="NewComment.CommentText" class="text-danger"></span>
</div>
<div class="col form-group">
<label asp-for="NewComment.EocDept" class="control-label"></label>
<input asp-for="NewComment.EocDept" class="form-control" />
<span asp-validation-for="NewComment.EocDept" class="text-danger"></span>
</div>
<div class="col-auto form-group align-self-end">
<input type="submit" value="Add Comment" class="btn btn-primary" />
</div>
</div>
</form>
<button id="getComments" class="btn btn-sm btn-outline-primary"><i class="fas fa-sync-alt"></i> Refresh Comments</button>
<div id="comments" class="mt-3">
<partial name="_CommentsPartial" model="Model.Incident.Comments.ToList()" />
</div>
<div class="mt-4">
<a asp-page="./Index">Back to Incident list</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
<script>
$(function () {
$('#getComments').on('click', function () {
$('#comments').load('/Incident?handler=CommentsPartial&id=' + @Model.Incident.Id.ToString());
});
});
</script>
}
@model List<Models.Comment>
<table class="table table-sm table-striped">
<thead>
<tr>
<th>@Html.DisplayNameFor(model => model.FirstOrDefault().EocDept)</th>
<th>@Html.DisplayNameFor(model => model.FirstOrDefault().EnterDateTime)</th>
<th>@Html.DisplayNameFor(model => model.FirstOrDefault().EnteredBy)</th>
<th>@Html.DisplayNameFor(model => model.FirstOrDefault().CommentText)</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>@Html.DisplayFor(modelItem => item.EocDept)</td>
<td>@Html.DisplayFor(modelItem => item.EnterDateTime)</td>
<td>@Html.DisplayFor(modelItem => item.EnteredBy)</td>
<td>@Html.DisplayFor(modelItem => item.CommentText)</td>
</tr>
}
</tbody>
</table>
Page model in Incident.cshtml.cs
public class IncidentModel : PageModel
{
private readonly MyDbContext _context;
public IncidentModel(MyDbContext context)
{
_context = context;
}
public Incident Incident { get; set; }
[BindProperty]
public Comment NewComment { get; set; }
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
return NotFound();
Incident = await _context.Incidents.FirstAsync(m => m.Id == id);
if (Incident == null)
return NotFound();
LoadSortedComments();
return Page();
}
public async Task<PartialViewResult> OnGetCommentsPartialAsync(int id)
{
Incident = await _context.Incidents.FirstAsync(m => m.Id == id);
LoadSortedComments();
return Partial("_CommentsPartial", Incident.Comments.ToList());
}
public void LoadSortedComments()
{
var entry = _context.Entry(Incident);
entry.Collection(e => e.Comments)
.Query()
.OrderByDescending(c => c.EnterDateTime)
.Load();
}
public async Task<IActionResult> OnPost(int id)
{
if (!ModelState.IsValid)
{
return Page();
}
// Is this the correct way to add the new Comment?
NewComment.IncidentId = id;
_context.Comments.Add(NewComment);
await _context.SaveChangesAsync();
// How do I refresh _CommentsPartial, and what gets returned here?
return ?????;
}
}
Questions:
- Is using the bound
NewComment
property the right way to get the new comment? (It is being added to the database, anyway.) - Is getting the Incident ID from the parameter in
OnPost
the right way to reference the page's incident? - What do I return from
OnPost
if I don't want to reload the entire page?