我正在通过js互操作从POST
向服务器发送一个Blazor
请求。发布请求到达服务器,经过计算,然后发回。 js
处理程序调用{{1}}以获得承诺,但数据不会返回到resolve
。
JS Interop
Blazor
控制器
window.methods={
submit: function () {
return new Promise((resolve, reject) => {
var form = document.getElementById("newTestForm");
var data = new FormData(form);
var xhr = new XMLHttpRequest();
var method = form.getAttribute('method');
var action = form.getAttribute('action');
xhr.open(method, action);
xhr.onload = function () {
if (xhr.status == 200) {
resolve(xhr.response); //data gets here in correct format !!!!!!!
}
else if (xhr.status != 200) {
reject("Failed to submit form with status" + xhr.status);
}
}
xhr.send(data);
});
}
}
Blazor组件
[HttpPost]
[Route("/myroute")]
public async Task<string> ReturnData()
{
await Task.Delay(1000);
return "hello";
}
响应正确,并且js方法<form method="post" action="/myroute">
....some inputs
</form>
<button onclick="@SubmitAsync"></button>
@functions{
public static async Task<string> SubmitNewTestAsync()
{
try
{
var data = await JSRuntime.Current.InvokeAsync<string>("methods.submit");
return data;
}
catch (Exception ex)
{
throw;
}
}
public async Task SubmitAsync()
{
string data= await SubmitNewTestAsync();
}
}
对结果调用submit
。我首先认为这可能是反序列化问题。但这不会引发任何错误。
我尝试了不同类型的响应(resolve
,bytes
,objects
),但仍然没有响应,也没有例外。
可能是什么问题?
PS ,因为我要停留在同一页面上,因此需要使用string
。自从我使用XMLHttpRequest
更新
好的,因此在尝试了许多事情之后,问题似乎出在Server-Side hosting
方面,特别是在Blazor
方法中。
似乎请求将完成而没有返回任何内容(也不会引发任何错误),除非JSRuntime.Current.InvokeAsync<Type>
是Type
/ primitive
/ object
,如果这不再是dynamic.
的特定问题,我现在就不这样做。 / p>
示例
考虑以下模型:
Blazor
这就是发生的事情(布拉泽尔一侧):
[Serializeable]
public class MyType{
public int value{get;set;}
}
到目前为止,还使用var data = await JSRuntime.Current.InvokeAsync<MyType>("methods.submit"); //fails
var data = await JSRuntime.Current.InvokeAsync<object>("methods.submit"); //works
var data = await JSRuntime.Current.InvokeAsync<dynamic>("methods.submit"); //works
,long
和int
进行了测试,它们都可以工作。
接收原语似乎没有问题。
答案 0 :(得分:2)
这可能是使用已删除的静态JSRuntime.Current属性的结果。相反,您应该将IJSRuntime注入到组件中,这样:
@inject IJSRuntime JSRuntime;
public static async Task<string> SubmitNewTestAsync()
{
try
{
var data = await JSRuntime.InvokeAsync<string>("methods.submit");
return data;
}
catch (Exception ex)
{
throw;
}
}
在您的JavaScript函数中尝试以下代码段:
xhr.onload = function () {
if (this.status >= 200 && this.status < 300) {
resolve(xhr.responseText);
} else {
reject("Failed to submit form with status" + xhr.status);
}
};
答案 1 :(得分:1)
我对Stripe付款承诺有同样的问题。 Call .NET methods from JavaScript functions in ASP.NET Core Blazor看起来是实现它的好方法。然后,我发现Blazor Javascript Interoperability博客文章很好地解决了问题。
这里只是一些准则,请在本文中休闲以了解概念。
JavaScript
function WithPromise(promiseHandler) {
var somePromise = promise.then((value) => {
promiseHandler.invokeMethodAsync('SetResult', JSON.stringify(value));
}
承诺处理程序
public class PromiseHandler : IPromiseHandler
{
public TaskCompletionSource<string> tcs { get; set; }
[JSInvokable]
public void SetResult(string json)
{
// Set the results in the TaskCompletionSource
tcs.SetResult(json);
}
}
从c#调用某些功能
public Task<string> SomePromiseCall()
{
var tcs = new TaskCompletionSource<string>();
var promiseHandler = DotNetObjectReference.Create<PromiseHandler>(new PromiseHandler() { tcs = tcs });
_jsRuntime.InvokeAsync<object>("WithPromise", promiseHandler);
return tcs.Task;
}