将可变数量的参数传递给Blazor Server应用程序中的本地API

huangapple go评论69阅读模式
英文:

Pass variable amount of parameters to local API in a Blazor Server app

问题

在我的Blazor Server应用程序中,我已经设置了一个API控制器来通过FastReport处理报告生成:

ReportController.cs

[Route("api/[controller]")]
[ApiController]
public class ReportController : ControllerBase
{
    [HttpGet("{reportName}")]
    public IActionResult GetReport(string reportName)
    {
        string reportPath = String.Format(@"pathtofilehere.frx", reportName);

        //TODO: 不同的导出类型处理
        string exportType = "application/pdf";
        string exportFileName = String.Format("{0}.pdf", reportName);

        WebReport web = new();
        web.Report.Load(reportPath);

        web.Report.SetParameterValue("CONN", @"connstringhere");

        //在这里处理参数

        web.Report.Prepare();

        MemoryStream stream = new();
        web.Report.Export(new FastReport.Export.PdfSimple.PDFSimpleExport(), stream);

        stream.Position = 0;

        return File(stream, exportType, exportFileName);
    }
}

我目前在我的某个页面中使用查询字符串调用这个API处理一些较小的参数,通过导航到API路由执行GET请求:

Reporting.razor

<div class="content-container">
    <input type="text" @bind-value="_startDate" />
    <button @onclick="DoSomething" type="submit">Download File</button>
</div>

@code {
    private async Task DoSomething()
    {
        string report = "report-2";
        string name = _startDate;

        NavManager.NavigateTo(string.Format("api/Report/{0}?name={1}", report, name), true);
    }
}

我有各种各样的参数需要传递给这些报告,例如开始日期、结束日期、用户ID等等。总共有大约40个参数,这些参数已经集成到我们现有的遗留站点中。我知道我可以在DoSomething中动态生成查询字符串,但我更希望能够传递一个可枚举的对象,以便根本不必处理查询字符串。我知道如果我执行POST请求,我可以传递一个JSON对象,但由于我需要实际导航到URL以下载文件,我认为我不能朝着这个方向前进。

我的初始想法是创建一个App State单例,它可以读取使用的参数,然后控制器可以提取它们,但是这个单例将被所有用户共享,如果多个用户尝试生成报告,将会导致一些干扰。

我正在尝试避免在服务器上生成PDF然后下载,这就是我使用API调用直接从流中下载的原因。

FastReport是我找到的最容易构建和生成PDF的工具,但我也愿意尝试其他免费软件。

英文:

I have an API controller set up in my Blazor Server app to handle report generation via FastReport:

ReportController.cs

[Route(&quot;api/[controller]&quot;)]
[ApiController]
public class ReportController : ControllerBase
{
    [HttpGet(&quot;{reportName}&quot;)]
    public IActionResult GetReport(string reportName)
    {
        string reportPath = String.Format(@&quot;pathtofilehere.frx&quot;, reportName);

        //TODO: different export type handling
        string exportType = &quot;application/pdf&quot;;
        string exportFileName = String.Format(&quot;{0}.pdf&quot;, reportName);

        WebReport web = new();
        web.Report.Load(reportPath);

        web.Report.SetParameterValue(&quot;CONN&quot;, @&quot;connstringhere&quot;);

        //handle parameters here

        web.Report.Prepare();

        MemoryStream stream = new();
        web.Report.Export(new FastReport.Export.PdfSimple.PDFSimpleExport(), stream);

        stream.Position = 0;

        return File(stream, exportType, exportFileName);
    }
}

I currently have calls to this handling some minor parameters via query strings in one of my pages, making a GET call by navigating to the API route:

Reporting.razor

&lt;div class=&quot;content-container&quot;&gt;
    &lt;input type=&quot;text&quot; @bind-value=&quot;@_startDate&quot; /&gt;
    &lt;button @onclick=&quot;DoSomething&quot; type=&quot;submit&quot;&gt;Download File&lt;/button&gt;
&lt;/div&gt;

@code {
    private async Task DoSomething()
    {
        string report = &quot;report-2&quot;;
        string name = _startDate;

        NavManager.NavigateTo(string.Format(&quot;api/Report/{0}?name={1}&quot;, report, name), true);
    }
}

I have a varying amount of parameters these reports will need to accept, such as start date, end date, user id, etc. There's about 40ish parameters total that we currently have built into our existing legacy site that will be built into this. I know I'll be able to generate a query string dynamically in my DoSomething, but I would prefer to be able to pass an enumerable object so I don't need to mess with the query string at all. I know I could pass in a JSON object if I was doing a POST, but since I need to actually navigate to the URL to download the file, I don't think I can move that direction.

My initial thoughts were to have an App State singleton that can just read the parameters used and then the controller can pull them out, but the singleton would be shared across all users, which would cause some interference if multiple users are trying to generate reports.

I am trying to avoid generating the PDF on the server and then downloading, which is the reason I'm using the API call to download directly from a stream.

FastReport is the easiest thing I've found to actual build and then generate PDFs, but I'm open to other freeware as well.

答案1

得分: 1

将报告生成器的参数存储在一个对象中,并将其存储在一个注入的 IMemoryCache 中,使用唯一的 Guid 作为键,然后将该键传递给您的控制器以检索该对象。

Blazor 组件:

<div class="content-container">
    <input type="text" @bind-value="_startDate" />
    <button @onclick="DoSomething" type="submit">Download File</button>
</div>
@code {
    [Inject]
    IMemoryCache cache;

    private async Task DoSomething()
    {
        ReportCreationParameters parameters = new ReportCreationParameters
        {
            Report = "report-2",
            Name = "_startDate"
        };

        Guid key = Guid.NewGuid();

        cache.Set(key, parameters);

        NavManager.NavigateTo(string.Format("api/Report/{0}", key), true);
    }
}

控制器:

[Route("api/[controller]")]
[ApiController]
public class ReportController : ControllerBase
{
    private readonly IMemoryCache cache;

    public ReportController(IMemoryCache cache)
    {
        this.cache = cache;
    }

    [HttpGet("{key}")]
    public IActionResult GetReport(Guid key)
    {
        // 从缓存中获取保存的参数。
        ReportCreationParameters parameters = cache.Get<ReportCreationParameters>(key);

        // 从缓存中删除保存的参数。
        cache.Remove(key);

        string reportPath = String.Format(@"pathtofilehere.frx", parameters.Name);

        //TODO: 处理不同的导出类型

        string exportType = "application/pdf";
        string exportFileName = String.Format("{0}.pdf", parameters.Name);

        WebReport web = new();
        web.Report.Load(reportPath);

        web.Report.SetParameterValue("CONN", @"connstringhere");

        // 在此处理参数

        web.Report.Prepare();

        MemoryStream stream = new();
        web.Report.Export(new FastReport.Export.PdfSimple.PDFSimpleExport(), stream);

        stream.Position = 0;

        return File(stream, exportType, exportFileName);
    }
}

希望这对您有所帮助!

英文:

Store the parameters for your report generator in an object and stash it in an injected IMemoryCache using a unique Guid as the key, then pass that key to your controller to retreive the object.

Blazor component:

&lt;div class=&quot;content-container&quot;&gt;
&lt;input type=&quot;text&quot; @bind-value=&quot;@_startDate&quot; /&gt;
&lt;button @onclick=&quot;DoSomething&quot; type=&quot;submit&quot;&gt;Download File&lt;/button&gt;

</div>

@code {
[Inject]
IMemoryCache cache;

private async Task DoSomething()
{
    ReportCreationParameters parameters = new ReportCreationParameters
    {
        Report = &quot;report-2&quot;,
        Name = &quot;_startDate&quot;
    };

    Guid key = Guid.NewGuid();

    cache.Set(key, parameters);

    NavManager.NavigateTo(string.Format(&quot;api/Report/{0}&quot;, key), true);
}
}

Controller:

[Route(&quot;api/[controller]&quot;)]
[ApiController]
public class ReportController : ControllerBase
{
    private readonly IMemoryCache cache;

    public ReportController(IMemoryCache cache)
    {
        this.cache = cache;
    }

    [HttpGet(&quot;{key}&quot;)]
    public IActionResult GetReport(Guid key)
    {
        // Fetch saved parameters from cache.
        ReportCreationParameters parameters = cache.Get&lt;ReportCreationParameters&gt;(key);

        // Remove saved parameters from cache.
        cache.Remove(key);

        string reportPath = String.Format(@&quot;pathtofilehere.frx&quot;, parameters.Name);

        //TODO: different export type handling
        string exportType = &quot;application/pdf&quot;;
        string exportFileName = String.Format(&quot;{0}.pdf&quot;, parameters.Name);

        WebReport web = new();
        web.Report.Load(reportPath);

        web.Report.SetParameterValue(&quot;CONN&quot;, @&quot;connstringhere&quot;);

        //handle parameters here

        web.Report.Prepare();

        MemoryStream stream = new();
        web.Report.Export(new FastReport.Export.PdfSimple.PDFSimpleExport(), stream);

        stream.Position = 0;

        return File(stream, exportType, exportFileName);
    }
}

huangapple
  • 本文由 发表于 2023年7月10日 22:28:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/76654746.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定