- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
已编辑:见底部
我是 SignalR 的新手,正在尝试通过使用此库和 ASP.NET Core Web API 的 Angular7 客户端来实现一个简单的场景。我所需要的只是使用 SignalR 通知客户端 API Controller 方法中一些冗长操作的进度。
经过多次尝试,我显然已经建立了连接,但是当长任务开始运行并发送消息时,我的客户端似乎没有收到任何东西,网络套接字中也没有任何流量出现( Chrome F12 - 网络 - WS)。
我在这里发布了详细信息,这可能对其他新手也有用(完整源代码 at https://1drv.ms/u/s!AsHCfliT740PkZh4cHY3r7I8f-VQiQ)。可能我只是犯了一些明显的错误,但在文档和谷歌搜索中我找不到与我的有本质区别的代码片段。谁能给个提示?
服务器端的起点是 https://msdn.microsoft.com/en-us/magazine/mt846469.aspx ,加上 https://learn.microsoft.com/en-us/aspnet/core/signalr/hubs?view=aspnetcore-2.2 处的文档.我试图用它创建一个虚拟实验解决方案。
我的代码片段以食谱的形式出现。
(A) 服务器端
1.创建一个新的 ASP.NET 核心 Web API 应用程序。没有身份验证或 Docker,只是为了保持最小化。
2. 添加 NuGet 包 Microsoft.AspNetCore.SignalR
.
3.at Startup.cs
, ConfigureServices
:
public void ConfigureServices(IServiceCollection services)
{
// CORS
services.AddCors(o => o.AddPolicy("CorsPolicy", builder =>
{
builder.AllowAnyMethod()
.AllowAnyHeader()
// https://github.com/aspnet/SignalR/issues/2110 for AllowCredentials
.AllowCredentials()
.WithOrigins("http://localhost:4200");
}));
// SignalR
services.AddSignalR();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
和对应的Configure
方法:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
// CORS
app.UseCors("CorsPolicy");
// SignalR: add to the API at route "/progress"
app.UseSignalR(routes =>
{
routes.MapHub<ProgressHub>("/progress");
});
app.UseHttpsRedirection();
app.UseMvc();
}
4.添加一个ProgressHub
类,仅派生自 Hub:
public class ProgressHub : Hub
{
}
5.添加一个TaskController
用一种方法开始一些冗长的操作:
[Route("api/task")]
[ApiController]
public class TaskController : ControllerBase
{
private readonly IHubContext<ProgressHub> _progressHubContext;
public TaskController(IHubContext<ProgressHub> progressHubContext)
{
_progressHubContext = progressHubContext;
}
[HttpGet("lengthy")]
public async Task<IActionResult> Lengthy([Bind(Prefix = "id")] string connectionId)
{
await _progressHubContext
.Clients
.Client(connectionId)
.SendAsync("taskStarted");
for (int i = 0; i < 100; i++)
{
Thread.Sleep(500);
Debug.WriteLine($"progress={i}");
await _progressHubContext
.Clients
.Client(connectionId)
.SendAsync("taskProgressChanged", i);
}
await _progressHubContext
.Clients
.Client(connectionId)
.SendAsync("taskEnded");
return Ok();
}
}
(B) 客户端
1.创建一个新的 Angular7 CLI 应用程序(没有路由,只是为了保持简单)。
2。 npm install @aspnet/signalr --save
.
3.我app.component
代码:
import { Component, OnInit } from '@angular/core';
import { HubConnectionBuilder, HubConnection, LogLevel } from '@aspnet/signalr';
import { TaskService } from './services/task.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
private _connection: HubConnection;
public messages: string[];
constructor(private _taskService: TaskService) {
this.messages = [];
}
ngOnInit(): void {
// https://codingblast.com/asp-net-core-signalr-chat-angular/
this._connection = new HubConnectionBuilder()
.configureLogging(LogLevel.Debug)
.withUrl("http://localhost:44348/signalr/progress")
.build();
this._connection.on("taskStarted", data => {
console.log(data);
});
this._connection.on("taskProgressChanged", data => {
console.log(data);
this.messages.push(data);
});
this._connection.on("taskEnded", data => {
console.log(data);
});
this._connection
.start()
.then(() => console.log('Connection started!'))
.catch(err => console.error('Error while establishing connection: ' + err));
}
public startJob() {
this.messages = [];
this._taskService.startJob('zeus').subscribe(
() => {
console.log('Started');
},
error => {
console.error(error);
}
);
}
}
它的极简 HTML 模板:
<h2>Test</h2>
<button type="button" (click)="startJob()">start</button>
<div>
<p *ngFor="let m of messages">{{m}}</p>
</div>
上面代码中的任务服务只是一个调用HttpClient
的函数的包装器。的 get<any>('https://localhost:44348/api/task/lengthy?id=' + id)
.
经过更多的试验,我做出了这些改变:
使用 .withUrl('https://localhost:44348/progress')
按照建议。似乎现在它不再触发 404。注意更改:我替换了 http
与 https
.
不要使 API 方法异步,因为看起来 await
不需要(即将返回类型设置为 IActionResult
并删除 async
和 await
)。
通过这些更改,我现在可以在客户端看到预期的日志消息 (Chrome F12)。看着它们,连接似乎绑定(bind)到生成的 ID k2Swgcy31gjumKtTWSlMLw
:
Utils.js:214 [2019-02-28T20:11:48.978Z] Debug: Starting HubConnection.
Utils.js:214 [2019-02-28T20:11:48.987Z] Debug: Starting connection with transfer format 'Text'.
Utils.js:214 [2019-02-28T20:11:48.988Z] Debug: Sending negotiation request: https://localhost:44348/progress/negotiate.
core.js:16828 Angular is running in the development mode. Call enableProdMode() to enable the production mode.
Utils.js:214 [2019-02-28T20:11:49.237Z] Debug: Selecting transport 'WebSockets'.
Utils.js:210 [2019-02-28T20:11:49.377Z] Information: WebSocket connected to wss://localhost:44348/progress?id=k2Swgcy31gjumKtTWSlMLw.
Utils.js:214 [2019-02-28T20:11:49.378Z] Debug: Sending handshake request.
Utils.js:210 [2019-02-28T20:11:49.380Z] Information: Using HubProtocol 'json'.
Utils.js:214 [2019-02-28T20:11:49.533Z] Debug: Server handshake complete.
app.component.ts:39 Connection started!
app.component.ts:47 Task service succeeded
因此,我可能没有收到通知,因为我的客户端 ID 与 SignalR 分配的 ID 不匹配(根据上面引用的论文,我的印象是提供 ID 是我的责任,因为它是 API Controller 的参数)。然而,我无法在连接原型(prototype)中看到任何可用的方法或属性来检索此 ID,因此我可以在启动冗长的作业时将其传递给服务器。这可能是我的问题的原因吗?如果是这样,应该有一种获取 ID 的方法(或从客户端设置它)。你怎么看?
最佳答案
看来我终于找到了。这个问题可能是由错误的ID引起的,所以我开始寻找解决方案。一篇文章 ( https://github.com/aspnet/SignalR/issues/2200) 指导我使用组,在这些情况下这似乎是推荐的解决方案。因此,我更改了集线器,使其自动将当前连接 ID 分配给“进度”组:
public sealed class ProgressHub : Hub
{
public const string GROUP_NAME = "progress";
public override Task OnConnectedAsync()
{
// https://github.com/aspnet/SignalR/issues/2200
// https://learn.microsoft.com/en-us/aspnet/signalr/overview/guide-to-the-api/working-with-groups
return Groups.AddToGroupAsync(Context.ConnectionId, "progress");
}
}
现在,我的 API Controller 方法是:
[HttpGet("lengthy")]
public async Task<IActionResult> Lengthy()
{
await _progressHubContext
.Clients
.Group(ProgressHub.GROUP_NAME)
.SendAsync("taskStarted");
for (int i = 0; i < 100; i++)
{
Thread.Sleep(200);
Debug.WriteLine($"progress={i + 1}");
await _progressHubContext
.Clients
.Group(ProgressHub.GROUP_NAME)
.SendAsync("taskProgressChanged", i + 1);
}
await _progressHubContext
.Clients
.Group(ProgressHub.GROUP_NAME)
.SendAsync("taskEnded");
return Ok();
}
当然,我相应地更新了客户端代码,因此在调用 API 方法时不再需要发送 ID。
完整的演示存储库可在 https://github.com/Myrmex/signalr-notify-progress 获得.
关于c# - SignalR : notifying progress of lengthy operation from ASP. NET Core Web API 到 Angular 7 客户端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54927044/
这对我来说似乎很简单,但我找不到合适的属性。出于错误报告的目的,我想知道我所在的内部过程的名称。 这是最简单的示例: 运行测试。 程序测试。 /* 如何在此处显示过程名称“test”? */ 结束程序
虽然这不是我的主要职责,但我从事 Progress 4GL 已经 8 年了。我更多地使用 C++ 和 Java。当用其他语言编程时,建议声明接近用法。然而,对于 4GL,我看到人们将声明放在文件的顶部
我注意到 Progress 4gl 中的 IF 语句有一个非常奇怪的行为。 我定义了一个格式为“999”的整数,它告诉它有 3 位数字,然后我分配一个小于 100 的值(例如 12),然后当我显示它时
我有下面的代码片段(如之前的 Stack Overflow 回答... Deleting all special characters from a string in progress 4GL 中所
如何将数字和字符串添加到 Progress4GL 上的字符变量中 如下所示(这只是一个展示想法的例子)。 a = 'Code' b = 1 c = a+b 所以c的值为“Code1” 我怎样才能在pr
我有一个缓冲区,其中混合了数据、数字和字符字段。我正在显示字段的值,但由于某种原因,日期字段返回“?”当我尝试将它们添加到字符串时。 我还明白吗?即使我这样做 ASSIGN lvString = lv
有没有办法用特定字符格式化正在进行的字符串? 一个示例显示了前 6 个数字为 x 的 SSN。我已尝试使用 String 函数,但它不支持以格式发送的字母 x。 SSNString = '333224
我正在寻找好的文献来学习 Progress 4GL。这是一个与工作空间相关的项目,无法获得培训资金。我试过文档,但它不准确且相当困惑。 我将不得不在 OE 10.1B 上的 ChUI 中完成大部分工作
我如何计算总数?表中的记录?我想显示数据库中的所有表名以及编号。每个表中的记录数 最佳答案 最快的方法是: proutil dbname -C tabanalys > dbname.tab 这是一个分
我正在创建某种音频播放器,但遇到了障碍。我添加了一个进度条,它会根据正在播放的歌曲进行更新。 但是,我希望进度条可以点击并在点击时跳转到轨道的时间(就像每个普通玩家一样)。
在我的进度应用程序中使用浏览器时,滚动条永远不会正常工作。它会显示我只能向下滚动一点,然后继续前进。这是一个正在进行的错误还是我可以做些什么来解决这个问题? /* Connected Database
我们如何更改 Progress 中的默认锁而不是共享锁? 最佳答案 您可以通过使用 [NO|EXCLUSIVE|SHARE]-LOCK 修饰符将锁定状态添加到查询来在每个单独的查询(FIND、FOR
我正在使用 Material-UI的 默认情况下转换 scaleX() 的组件 的属性在另一个里面 每当值更改以可视化当前进度时。它具有缓动效果,使一切看起来都很流畅,这通常非常好,但是出于我的应用程
我很好奇 PWA 添加到主屏幕后将在后台使用什么浏览器。它是您最初选择“添加到主屏幕”的那个吗?如果是,如果我在我的 Chrome 上将 PWA 添加到主屏幕怎么办手机,然后删除 Chrome(假设现
在我问任何问题之前,让我告诉你我对 Progress Openedge 没有任何经验,但我的公司运行一个用它制作的应用程序,现在我必须通过它进行一些 SOAP 调用。所以我想,为什么不调用用我认为合适
在我提出任何问题之前,让我告诉你我对 Progress Openedge 没有任何经验,但我的公司运行一个用它制作的应用程序,现在我必须通过它进行一些 SOAP 调用。所以我想,为什么不调用用我认为合
进度处理程序已在一些领先的 promise 库(Q、When、Bluebird)中弃用,并且也已从新的 Promises/A+ spec 中删除。虽然我理解取消进度事件背后的原因,但我在重构以下我
如何改变的颜色 progress[value]::-webkit-progress-value { background-color: #00bdf8;
我有一个需要连接的进度数据库。它们与 SQL Server Management Studio 的等价物是什么? 服务器似乎是 Progress OpenEdge 10.1 最佳答案 这在一定程度上取
我在不了解 PWA 的内在含义的情况下开始构建 PWA。当我搜索时,PWA 使用以下技术逐步为 Web 应用程序提供了类似于外观的原生应用程序 舱单 服务人员 设计App shell Web 应用程序
我是一名优秀的程序员,十分优秀!