Have a Solution with 2 Projects, Report and Web developed in .net core 2.1 using AlanJudenMvcReportViewer which is working ok on about a dozen SSRS server reports.
Decided to use Microsoft.DotNet.UpgradeAssistant to migrate to net 5.0. Struck many errors which I have overcome with the exception of this one:
Running any report in net 5.0 now gives me ‘Report failed to load, check report parameters’ which is actually a 500 / internal server error:
System.MissingMethodException: Method not found: ‘Microsoft.AspNetCore.Mvc.JsonResult Microsoft.AspNetCore.Mvc.Controller.Json(System.Object, Newtonsoft.Json.JsonSerializerSettings)’.
The error is occuring in ReportViewer.cshtml/viewReportPage at : $.get("/Report/ViewReportPage/[email protected]()&page=" + page + "&" + urlParams)
Some research gave me: https://github.com/alanjuden/MvcReportViewer/issues/92 (and others):
… There are two solutions, one involves modifying the ReportController from Alan’s code, and the other involves including a package reference and modifying your startup to instruct MVC to use Newtonsoft JSON.
Option #1: In MvcReportViewer/ReportController/ViewReportPage method, completely replace the following code
new Newtonsoft.Json.JsonSerializerSettings() { ContractResolver = new Newtonsoft.Json.Serialization.DefaultContractResolver() });
with… new System.Text.Json.JsonSerializerOptions());
Option #2: First add a package reference to your .csproj file for your project in the ItemGroup that contains your other package references…
Then, in your Startup.cs/ConfigureServices method, instruct MVC to use Newtonsoft JSON… services.AddMvc().AddNewtonsoftJson();….
Have tried Option #2 – no change, same error.
Dont know how to apply Option #1 as I dont see the code to replace (and that may be the problem).
Have seen reference to problems with using earlier version packages.As far as I can see I have updated all of mine.
The ReportController.cs I am using is :
using System.Net;
using Microsoft.AspNetCore.Mvc;
using SSFA_Web.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Authorization;
namespace SSFA_Web.Controllers
{
[Authorize]
public class ReportController : AlanJuden.MvcReportViewer.ReportController
{
private readonly SSFA_SQLContext _context;
public ReportController(SSFA_SQLContext context)
{
_context = context;
}
protected override ICredentials NetworkCredentials
{
get
{
return new System.Net.NetworkCredential("Myusername", "Mypassword", "Mydomain");
}
}
protected override System.ServiceModel.HttpClientCredentialType ClientCredentialType
{
get
{
return System.ServiceModel.HttpClientCredentialType.Ntlm;
}
}
protected override string ReportServerUrl
{
get
{
return "http://MyReportServer directory";
}
}
protected override bool UseCustomReportImagePath { get { return true; } }
protected override string ReportImagePath
{
get
{
return "/Report/ReportImage/?originalPath={0}";
}
}
public ActionResult CalendarListing()
{
var model = this.GetReportViewerModel(Request);
model.ReportPath = "/Reports/CalendarListing";
return View("ReportViewer", model);
}
// etc
}
}
The ReportViewer.cshtml is :
@model AlanJuden.MvcReportViewer.ReportViewerModel
@using AlanJuden.MvcReportViewer
@{
ViewBag.Title = "ReportViewer";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>ReportViewer</h2>
@section AdditionalHeadContent {
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/select2.min.css" />
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/select2-bootstrap.min.css" />
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/mvcreportviewer-bootstrap.css" />
<style>
.row {
margin-left: 0;
margin-right: 0;
}
</style>
<script src="~/lib/bootstrap/dist/js/select2.min.4.0.3.js"></script>
<script src="~/lib/jquery/dist/jquery.highlight-5.js"></script>
<script>
$(document).ready(function () {
_initializeReportViewerControls();
$('.FirstPage, .ViewReport, .Refresh').click(function () {
if (!$(this).attr('disabled')) {
viewReportPage(1);
}
});
$('.PreviousPage').click(function () {
if (!$(this).attr('disabled')) {
var page = parseInt($('#ReportViewerCurrentPage').val()) - 1;
viewReportPage(page);
}
});
$('.NextPage').click(function () {
if (!$(this).attr('disabled')) {
var page = parseInt($('#ReportViewerCurrentPage').val()) + 1;
viewReportPage(page);
}
});
$('.LastPage').click(function () {
if (!$(this).attr('disabled')) {
var page = parseInt($('#ReportViewerTotalPages').text());
viewReportPage(page);
}
});
$('#ReportViewerCurrentPage').change(function () {
var page = $(this).val();
viewReportPage(page);
});
$('.ExportXml, .ExportCsv, .ExportPdf, .ExportMhtml, .ExportExcelOpenXml, .ExportTiff, .ExportWordOpenXml').click(function () {
exportReport($(this));
});
$('#ReportViewerSearchText').on("keypress", function (e) {
if (e.keyCode == 13) {
// Cancel the default action on keypress event
e.preventDefault();
findText();
}
});
$('.FindTextButton').click(function () {
findText();
});
$('.Print').click(function () {
printReport();
});
});
function _initializeReportViewerControls() {
$('select').select2();
try {
ReportViewer_Register_OnChanges();
} catch (e) { }
}
function reloadParameters() {
var params = $('.ParametersContainer :input').serializeArray();
var urlParams = $.param(params);
showLoadingProgress("Updating Parameters...");
$.get("/Report/ReloadParameters/[email protected]()&" + urlParams).done(function (data) {
if (data != null) {
$('.Parameters').html(data);
_initializeReportViewerControls();
if ($('.ReportViewerContent').find('div').length != 1) {
$('.ReportViewerContent').html('<div class="ReportViewerInformation">Please fill parameters and run the report...</div>');
}
}
hideLoadingProgress();
});
}
function showLoadingProgress(message) {
hideLoadingProgress();
$('.ReportViewerContent').hide();
$('.ReportViewerContentContainer').append('<div class="loadingContainer"><div style="margin: 0 auto; width: 100%; text-align: center; vertical-align: middle;"><h2><i class="glyphicon glyphicon-refresh gly-spin"></i>' + message + '</h2></div></div>');
}
function hideLoadingProgress() {
$('.loadingContainer').remove();
$('.ReportViewerContent').show();
}
function printReport() {
var params = $('.ParametersContainer :input').serializeArray();
var urlParams = $.param(params);
window.open("/Report/PrintReport/[email protected]()&" + urlParams, "_blank");
}
function findText() {
$('.ReportViewerContent').removeHighlight();
var searchText = $("#ReportViewerSearchText").val();
if (searchText != undefined && searchText != null && searchText != "") {
showLoadingProgress('Searching Report...');
var params = $('.ParametersContainer :input').serializeArray();
var urlParams = $.param(params);
var page = parseInt($('#ReportViewerCurrentPage').val());
$.get("/Report/FindStringInReport/[email protected]()&page=" + page + "&searchText=" + searchText + "&" + urlParams).done(function (data) {
if (data > 0) {
viewReportPage(data, function () {
$('.ReportViewerContent').highlight(searchText);
hideLoadingProgress();
});
} else {
$('.ReportViewerContent').highlight(searchText, { wholeWord: false, ignoreCase: true, color: "#ffff00", bold: true });
hideLoadingProgress();
}
});
}
}
function viewReportPage(page, afterReportLoadedCallback) {
showLoadingProgress('Loading Report Page...');
var params = $('.ParametersContainer :input').serializeArray();
var urlParams = $.param(params);
var totalPages = parseInt($('#ReportViewerTotalPages').text());
if (page == undefined || page == null || page < 1) {
page = 1;
} else if (page > totalPages) {
page = totalPages;
}
$.get("/Report/ViewReportPage/[email protected]()&page=" + page + "&" + urlParams)
.done(function (data) {
updateReportContent(data);
hideLoadingProgress();
if (afterReportLoadedCallback && typeof (afterReportLoadedCallback) == "function") {
afterReportLoadedCallback();
}
})
.fail(function (data) {
$('.ReportViewerContent').html("<div class='ReportViewerError'>Report failed to load, check report parameters...</div>");
hideLoadingProgress();
});
}
function exportReport(element) {
var params = $('.ParametersContainer :input').serializeArray();
var urlParams = $.param(params);
var format = $(element).attr('class').replace("Export", "");
window.location.href = "/Report/ExportReport/[email protected]()&format=" + format + "&" + urlParams;
}
function updateReportContent(data) {
if (data != undefined && data != null) {
$('#ReportViewerCurrentPage').val(data.CurrentPage);
$('#ReportViewerTotalPages').text(data.TotalPages);
$('.ReportViewerContent').html($.parseHTML(data.Content));
if (data.TotalPages <= 1) {
$('.FirstPage').attr('disabled', true);
$('.PreviousPage').attr('disabled', true);
$('.NextPage').attr('disabled', true);
$('.LastPage').attr('disabled', true);
} else {
$('.FirstPage').attr('disabled', false);
$('.PreviousPage').attr('disabled', false);
$('.NextPage').attr('disabled', false);
$('.LastPage').attr('disabled', false);
}
}
}
</script>
}
@section Content {
@Html.RenderReportViewer(Model)
}
Any help would be appreciated.
2
Answers
Answer: (Which I only partially understand)
Thanks to both @Nick.McDermaid and @JonasH for your help.
Went back to AlanJuden GitHub and found another Controller of his with a different Method for the ViewReportPage with reference to the code mentioned in Option #1.
Copied this into my Controller (with a few mods for errors and changes for System.Text.Json mentioned earlier as Option #1) to try and get System.Text.Json.JsonSerializerOptions() working.
IE Added following to ReportController.cs before report ActionResults.
When I run this, at the $get code (F12 Developer Tools/network tab/body) I get a different 500 error - The request matched multiple endpoints. Matches: SSFA_Web.Controllers.ReportController.ViewReportPage (SSFA_Web) SSFA_Web.Controllers.ReportController.ViewReportPage (SSFA_Web)
I assume 1 from my Controller mods and 1 from AlanJudens dll.
Eventually (several days later) found that this works:
Changed ReportController.cs/JsonResult:
From public new JsonResult ViewReportPage(string reportPath, int? page = 0)
To public JsonResult ViewReportPageX(string reportPath, int? page = 0)
Changed ReportViewer.cshtml/viewReportPage
From $.get("/Report/viewReportPage/[email protected]()&page=" + page + "&" + urlParams)
To $.get("/Report/viewReportPageX/[email protected]()&page=" + page + "&" + urlParams)
Most probably not how it should be done but it works.
I’m not sure if this is helpful, but the signature apparently have changed from
to
With the documentation
So, presumably the method should still accept the same object. But if you have something that uses the old method signature you either need to update the reference, or need to update the library that calls that method. After all, method resolution happens when you compile the source code. When it reaches the jitter the method signatures need to match exactly.
I’m unfortunately not sufficient knowledagble about asp.net, nor .net core 2 vs .net 5 to provide more specific suggestions.