.NET Core 3.1 - Ajax OnGet и возврат объектов с помощью НОВОГО System.Text.Json
Сегодня я впервые столкнулся с этой проблемой, когда пытался вернуть массив объектов из запроса LINQ, который содержит поле внешнего ключа. Отказ Microsoft от Newtonsoft JSON Library для.NET Core 3+ заставил меня не знать, как выполнить эквивалентный метод, показанный ниже:
Пример ниже использовался для работы в Core 2.2, но теперь выдает ошибку "System.Text.Json.JsonException: обнаружен возможный цикл объекта, который не поддерживается. Это может происходить либо из-за цикла, либо из-за того, что глубина объекта превышает максимально допустимую глубину 32 ".
public async Task<IActionResult> OnGetSelectAllReportTemplatesAsync()
{
// Get the currently logged in user.
var currentlyLoggedInUser = await _userManager.GetUserAsync(User);
// Note - ApplicationUserId is a foreign key field in the DB Table...
var reportTemplates = _context.ReportTemplate
.Where(s => s.Private == true & s.ApplicationUserId == currentlyLoggedInUser.Id)
.OrderBy(s => s.Name).ToListAsync();
return new JsonResult(reportTemplates);
}
Ajax Call ниже:
$.ajax({
type: "GET",
url: "/Reports/ListView?handler=SelectAllReportTemplates",
contentType: "json",
dataType: "json",
success: function (data) {
data.forEach(function (element) {
$("#editReportTemplateSelect").append('<option value="' + element.id + '">' + element.name + '</option>');
reportTemplatesArray.push({ id: '' + element.id + '', name: '' + element.name + '', description: '' + element.description + '', timePeriod: '' + element.timePeriod + '', startDate: '' + element.startDate + '', startTimeHours: '' + element.startTimeHours + '', startTimeMinutes: '' + element.startTimeMinutes + '', endDate: '' + element.endDate + '', endTimeHours: '' + element.endTimeHours + '', endTimeMinutes: '' + element.endTimeMinutes + '', logLevel: '' + element.logLevel + '', eventCategory: '' + element.eventCategory + '', eventType: '' + element.eventType + '', eventSource: '' + element.eventSource + '', userAccount: '' + element.userAccount + '', private: '' + element.private + '', });
});
$("#reportTemplateNameInput").val(''); // Clear the department name input field.
$('#reportTemplateDescriptionTextarea').val(''); // Clear the department description textarea.
},
error: function () {
$("#editreportTemplateSelectMessageBar").html("Error while making Ajax call!");
setTimeout(function () { $("#editreportTemplateSelectMessageBar").html(''); }, 5000);
}
});
Я попытался пометить поле внешнего ключа в классе модели атрибутом "[JsonIgnore]", поскольку мне действительно не нужно читать вложенные свойства из других таблиц, все, что мне нужно, это само строковое значение ApplicationUserId. Единственная причина, по которой у меня есть таблицы, использующие отношения, - это каскадное удаление.
Я не могу найти примеры кода, объясняющие, как использовать новую систему?
1 ответ
Хорошо, поэтому я немного пересек свои провода здесь, после установки прежних функций JSON (патч Microsoft.AspNetCore.Mvc.NewtonsoftJson) в качестве NuGet обратно в проект, я все еще получал ошибку цикла объекта.
Мое решение заключалось в том, чтобы установить поле внешнего ключа в классе модели с атрибутом [JsonIgnore], затем я обновил метод OnGet, как показано ниже. В этом методе теперь используется более упрощенный запрос LINQ, который прошел без ошибок, затем я вручную выполняю фильтрацию из выбранных послесловий, создавая список, который затем можно вернуть обратно в функцию Ajax GET.
Класс модели:
public class ReportTemplate
{
public int Id { get; set; } // Primary Key
other parameter object here...
[Required]
[JsonIgnore]
public string ApplicationUserId { get; set; }
[JsonIgnore]
public ApplicationUser ApplicationUser { get; set; }
}
Модель страницы Razor:
public async Task<IActionResult> OnGetSelectAllReportTemplates()
{
// Get the currently logged in user.
var currentlyLoggedInUser = await _userManager.GetUserAsync(User);
// Create a List
List<ReportTemplate> reportTemplates = new List<ReportTemplate>();
// Run a simple get all LINQ query
var reports = _context.ReportTemplate.OrderBy(s => s.Name);
// Do the filtering, manually from the query collection
foreach (var report in reports)
{
if (report.Private == false)
{
reportTemplates.Add(report);
}
if (report.Private == true & report.ApplicationUserId == currentlyLoggedInUser.Id)
{
reportTemplates.Add(report);
}
}
return new JsonResult(reportTemplates);
}