如何从API端点接收响应以绑定到Blazor服务器项目中的DataTable。

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

How to receive response from an API endpoint to bind the DataTablein Blazor server project

问题

以下是我为您翻译的代码部分:

以下是我用于绑定 DataTable 的代码这段代码在 MVC 项目中与 MVC 控制器一起使用时可以正常工作但在尝试与 API 控制器一起使用时出现问题

window.UpcomingPaymentTables = {
    dataTable: null,

    buildDataTable: function () {
        this.dataTable = $("#UpcomingPaymentsGrid").DataTable({
            columnDefs: [
                { targets: [0], data: "Date" },
                { targets: [1], data: "Amount" }
            ],
            processing: true,
            stateSave: true,
            serverSide: true,
            filter: true,
            lengthMenu: [[10, 25, 50], [10, 25, 50]],
            autoWidth: false,
            ajax: {
                url: "/api/Plans/GetUpcomingPayments",
                type: 'POST',
                dataFilter: function (resp) {
                    debugger;
                    return resp;
                },
                error: function (xhr, error, code) {
                    alert(error);
                }
            }
        });
    },
    destroyDataTable: function () {
        if (this.dataTable) {
            this.dataTable.destroy();
        }
    }
}

在 dataFilter 中收到一个空的 "resp" 变量。

以下是 API 端点:

[HttpPost]
[Route("GetUpcomingPayments")]
public DataTablesResult GetUpcomingPayments([FromForm] DataTablesRequest request)
{
    var data = _planService.GetUpcomingPayments(122).ReadDataTable(request);
    
    DataTablesResult rs = new DataTablesResult(data);
    return rs;
}

DataTablesResult 具有 DataTable 所需的所有属性。与 MVC 控制器一起,相同的代码正常工作。唯一的区别是我正在尝试与 API 控制器一起使用。在 API 控制器中,我必须使用 [FromForm] 将 DataTablesRequest 对象传递,而在 MVC 控制器中则不需要。

在 Razor 组件上使用以下代码来调用 JavaScript 函数:

protected override async Task OnAfterRenderAsync(bool firstRender)
{
    if (firstRender)
    {
        await _jsRuntime.InvokeVoidAsync("UpcomingPaymentTables.destroyDataTable");
        await _jsRuntime.InvokeVoidAsync("UpcomingPaymentTables.buildDataTable");
    }       
}

我在 API 控制器中是否遗漏了一些内容以返回所需格式的数据?


请注意,翻译文本中的 `"` 实际上是 HTML 编码的双引号,您在代码中应该使用双引号 `"`. 此外,翻译文本中的 `'` 实际上是 HTML 编码的单引号,您在代码中应该使用单引号 `'`.

<details>
<summary>英文:</summary>

Below is the `code` I&#39;m using to bind `DataTable`. This same code works fine with an `MVC` project with `MVC controller`. But facing problems when trying the same code with `API controller.`

     `window.UpcomingPaymentTables = {
       dataTable: null,

    buildDataTable: function () {
        this.dataTable = $(&quot;#UpcomingPaymentsGrid&quot;).DataTable({
            columnDefs: [
                { targets: [0], data: &quot;Date&quot; },
                { targets: [1], data: &quot;Amount&quot; }
            ],
            processing: true,
            stateSave: true,
            serverSide: true,
            filter: true,
            lengthMenu: [[10, 25, 50], [10, 25, 50]],
            autoWidth: false,
            ajax: {
                url: &quot;/api/Plans/GetUpcomingPayments&quot;,
                type: &#39;POST&#39;,
                dataFilter: function (resp) {
                    debugger;
                    return resp;
                },
                error: function (xhr, error, code) {
                    alert(error);
                }
            }
        });
    },
    destroyDataTable: function () {
        if (this.dataTable) {
            this.dataTable.destroy();
        }
    }
      }`

Receiving an empty `object` in &quot;resp&quot; variable of dataFilter.

Below is the `API` endpoint:

        [HttpPost]
        [Route(&quot;GetUpcomingPayments&quot;)]
        public DataTablesResult GetUpcomingPayments([FromForm] DataTablesRequest request)
        {
            var data = _planService.GetUpcomingPayments(122).ReadDataTable(request);
            
            DataTablesResult rs = new DataTablesResult(data);
            return rs;
        }

`DataTablesResult` has all the required `properties` for `Datatable`. The same code is working for the `MVC controller`. the only difference is I&#39;m trying it with `API Controller`.
In `API Controller` I had to pass the DataTablesRequest object using [FromForm] while in `MVC controller` it doesn&#39;t need.

Using the following `code` on a `razor component` to call the `js` functions.

protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await _jsRuntime.InvokeVoidAsync("UpcomingPaymentTables.destroyDataTable");
await _jsRuntime.InvokeVoidAsync("UpcomingPaymentTables.buildDataTable");
}

}

Am I missing something in `API controller` to return the data in the required format?

</details>


# 答案1
**得分**: 0

```plaintext
**更新:**

不要定义 `$upcomingTable` 和 `udt`,直接使用它们,因为你正在调用 `window.UpcomingPaymentTables`,在外部无法识别定义:

```javascript
window.UpcomingPaymentTables = {
    buildDataTable: function () {
        this.dataTable = $(&quot;#UpcomingPaymentsGrid&quot;).DataTable({
            //...
        });
    },
    destroyDataTable: function () {
        if (this.dataTable) {
            this.dataTable.destroy();
        }
    }
}

相应的数据没有在你的 ajax 请求中传递,这将导致 Api 调用失败。在 Api 返回的 JSON 中,默认情况下键名都是小写。此外,我不确定你返回的 rs 是什么样子的,但请确保它是 List/Array/Enumerable 类型。

以下是一个可工作的演示,你可以参考它(为了方便起见,我只是使用了 DataTablesRequest 模型):

public class DataTablesRequest
{ 
    public string Date { get; set; }
    public string Amount { get; set; }
}

[Route(&quot;api/[controller]&quot;)]
[ApiController]
public class TestController : ControllerBase
{
    [HttpPost]
    [Route(&quot;GetUpcomingPayments&quot;)]
    public List&lt;DataTablesRequest&gt; Get([FromForm] DataTablesRequest request)
    {
        var Request = new DataTablesRequest() 
        {
            Date = &quot;Date1&quot;,
            Amount = &quot;Amount1&quot;
        };

        var RequestList = new List&lt;DataTablesRequest&gt;() { Request };
        return RequestList;
    }
}

DataTables.razor:

@page &quot;/datatables&quot;
@implements IDisposable
@using BlazorApp.Shared
@inject HttpClient Http
@inject IJSRuntime JS

<table class=&quot;table&quot; id=&quot;dt2&quot;>
    <thead>
        <tr>
            <th>Date</th>
            <th>Amount</th>
        </tr>
    </thead>
</table>

@code {
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        await base.OnAfterRenderAsync(firstRender);

        if (firstRender)
        {
            await JS.InvokeVoidAsync(&quot;DataTables.buildDataTable&quot;);
        }
    }

    async void IDisposable.Dispose()
    {
        await JS.InvokeVoidAsync(&quot;DataTables.destroyDataTable&quot;);
    }
}

DataTables.js:

window.DataTables = {
    dataTable: null,
    buildDataTable: function (ajaxUrl) {
        var data = {
            &quot;Date&quot;: &quot;TestDate&quot;,
            &quot;Amount&quot;: &quot;TestAmount&quot;
        }
        this.dataTable = $(&quot;#dt2&quot;).DataTable({
            &quot;ajax&quot;: {
                &quot;url&quot;: &quot;/api/Test/GetUpcomingPayments&quot;,
                &quot;type&quot;: &quot;POST&quot;,
                &quot;data&quot;: data,
                &quot;dataSrc&quot;: &quot;&quot;,
                &quot;dataFilter&quot;: function (resp) {
                    debugger;
                    return resp;
                },
                &quot;error&quot;: function (xhr, error, code) {
                    alert(error);
                }
            },
            columnDefs: [
                //小写
                { targets: [0], data: &quot;date&quot; },
                { targets: [1], data: &quot;amount&quot; }
            ],
            processing: true,
            stateSave: true,
            filter: true,
            lengthMenu: [[10, 25, 50], [10, 25, 50]],
            autoWidth: false
        });
    },
    destroyDataTable: function () {
        if (this.dataTable) {
            this.dataTable.destroy();
        }
    }
}

不要忘记引用 JS 文件:

<script src=&quot;js/DataTables.js&quot;></script>

测试结果:

如何从API端点接收响应以绑定到Blazor服务器项目中的DataTable。

如何从API端点接收响应以绑定到Blazor服务器项目中的DataTable。

如何从API端点接收响应以绑定到Blazor服务器项目中的DataTable。


<details>
<summary>英文:</summary>
**Update:**
Do not define `$upcomingTable` and `udt`, use them directly, because you are calling `window.UpcomingPaymentTables`, the definition is not recognized externally:
window.UpcomingPaymentTables = {
buildDataTable: function () {
this.dataTable = $(&quot;#UpcomingPaymentsGrid&quot;).DataTable({
//...
});
},
destroyDataTable: function () {
if (this.dataTable) {
this.dataTable.destroy();
}
}
}
*******************************************
The corresponding data is not passed in your `ajax` request, which will cause the Api call to fail. In the JSON returned from the Api, the keys are all lowercase by default. Also, I&#39;m not sure how the `rs` you return look like, but make sure it&#39;s of type `List/Array/Enumerable`.
Below is a working demo, you can refer to it (For convenience, I just used the `DataTablesRequest` model).
DataTablesRequest:
public class DataTablesRequest
{ 
public string Date { get; set; }
public string Amount { get; set; }
}
TestController:
[Route(&quot;api/[controller]&quot;)]
[ApiController]
public class TestController : ControllerBase
{
[HttpPost]
[Route(&quot;GetUpcomingPayments&quot;)]
public List&lt;DataTablesRequest&gt; Get([FromForm] DataTablesRequest request)
{
var Request = new DataTablesRequest() 
{
Date = &quot;Date1&quot;,
Amount = &quot;Amount1&quot;
};
var RequestList = new List&lt;DataTablesRequest&gt;() { Request };
return RequestList;
}
}
DataTables.razor:
@page &quot;/datatables&quot;
@implements IDisposable
@using BlazorApp.Shared
@inject HttpClient Http
@inject IJSRuntime JS
&lt;table class=&quot;table&quot; id=&quot;dt2&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Date&lt;/th&gt;
&lt;th&gt;Amount&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;/table&gt;
@code {
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await base.OnAfterRenderAsync(firstRender);
if (firstRender)
{
await JS.InvokeVoidAsync(&quot;DataTables.buildDataTable&quot;);
}
}
async void IDisposable.Dispose()
{
await JS.InvokeVoidAsync(&quot;DataTables.destroyDataTable&quot;);
}
}
DataTables.js:
window.DataTables = {
dataTable: null,
buildDataTable: function (ajaxUrl) {
var data = {
&quot;Date&quot;: &quot;TestDate&quot;,
&quot;Amount&quot;: &quot;TestAmount&quot;
}
this.dataTable = $(&quot;#dt2&quot;).DataTable({
&quot;ajax&quot;: {
&quot;url&quot;: &quot;/api/Test/GetUpcomingPayments&quot;,
&quot;type&quot;: &quot;POST&quot;,
&quot;data&quot;: data,
&quot;dataSrc&quot;: &quot;&quot;,
&quot;dataFilter&quot;: function (resp) {
debugger;
return resp;
},
&quot;error&quot;: function (xhr, error, code) {
alert(error);
}
},
columnDefs: [
//lowercase
{ targets: [0], data: &quot;date&quot; },
{ targets: [1], data: &quot;amount&quot; }
],
processing: true,
stateSave: true,
filter: true,
lengthMenu: [[10, 25, 50], [10, 25, 50]],
autoWidth: false
});
},
destroyDataTable: function () {
if (this.dataTable) {
this.dataTable.destroy();
}
}
}
Don&#39;t forget to reference the JS file:
&lt;script src=&quot;js/DataTables.js&quot;&gt;&lt;/script&gt;
Test Result:
[![enter image description here][1]][1]
[![enter image description here][2]][2]
[![enter image description here][3]][3]
[1]: https://i.stack.imgur.com/UZrB7.png
[2]: https://i.stack.imgur.com/98NfP.png
[3]: https://i.stack.imgur.com/aLzgb.png
</details>

huangapple
  • 本文由 发表于 2023年6月30日 00:01:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/76582764.html
匿名

发表评论

匿名网友

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

确定