gpt4 book ai didi

javascript - 无法使 SignalR、Web API 和 SystemJS 一起工作

转载 作者:行者123 更新时间:2023-11-28 05:39:53 25 4
gpt4 key购买 nike

我正在尝试在 Web API 上构建通知服务,以通知 JavaScript (Aurelia) 客户端 (WebApp)。我的 Web API 和 WebApp 位于不同的域中。

我有一个简单的NotificationHub:

public class NotificationHub:Hub
{
public void NotifyChange(string[] values)
{
Clients.All.broadcastChange(values);
}
}

我在 Web API 的 Startup 中配置 SignalR,如下所示:

public void Configuration(IAppBuilder app)
{
HttpConfiguration httpConfig = new HttpConfiguration();

var cors = new EnableCorsAttribute("http://localhost:9000", "*", "*");
httpConfig.EnableCors(cors);

app.MapSignalR();

WebApiConfig.Register(httpConfig);
...
}

在我的 Web 应用程序中,我尝试从我的 Web API 访问 signalr/hubs,如下所示:

Promise.all([...
System.import('jquery'),
System.import('signalr'), ...
])
.then((imports) => {
return System.import("https://localhost:44304/signalr/hubs");
});

我还在我的 config.js 中添加了一个 meta 部分:

System.config({
...
meta: {
"https://*/signalr/hubs": { //here I also tried with full url
"format": "global",
"defaultExtension": false,
"defaultJSExtension": false,
"deps": ["signalr"]
}
}
});

尽管进行了这些配置,我仍然遇到以下问题:

  1. 来自 WebApp 的 signalr/hubs 请求采用 https://localhost:44304/signalr/hubs.jsHTTP返回 404。请注意,浏览 https://localhost:44304/signalr/hubs 将返回 hubs 脚本。
  2. $.connection("https://localhost:44304/signalr").start() 上,我收到以下错误:

XMLHttpRequest cannot load https://localhost:44304/signalr/negotiate?clientProtocol=1.5&_=1471505254387. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:9000' is therefore not allowed access.

请让我知道我在这里缺少什么?

更新:使用适当的 CORS 配置,以及 gist由 @kabaehr 建议,我现在可以连接到 SignalR 集线器。但是,广播(推送通知)仍然不起作用。

我的 SignalR 配置:

public static class SignalRConfig
{
public static void Register(IAppBuilder app, EnableCorsAttribute cors)
{

app.Map("/signalr", map =>
{
var corsOption = new CorsOptions
{
PolicyProvider = new CorsPolicyProvider
{
PolicyResolver = context =>
{
var policy = new CorsPolicy { AllowAnyHeader = true, AllowAnyMethod = true, SupportsCredentials = true };

// Only allow CORS requests from the trusted domains.
cors.Origins.ForEach(o => policy.Origins.Add(o));

return Task.FromResult(policy);
}
}
};
map.UseCors(corsOption).RunSignalR();
});
}
}

我在启动中使用它,如下所示:

var cors = new EnableCorsAttribute("http://localhost:9000", "*", "*");
httpConfig.EnableCors(cors);

SignalRConfig.Register(app, cors);

WebApiConfig.Register(httpConfig);

我正在尝试按如下方式推送通知:

GlobalHost.ConnectionManager.GetHubContext<NotificationHub>().Clients.All.broadcastChange(new[] { value });

但是,我的客户没有收到关于 broadcastChange 的通知。我假设当我使用 gist 时,我不必显式导入 https://localhost:44304/signalr/hubs .

最佳答案

这只是为了分享我的发现以及为我解决问题的方法。

首先,signalr/hubs 只是服务器端代码自动生成的代理。如果您可以创建自己的 SignalR 代理客户端,则无需使用该代理。下面是一个基于 gist 创建的简单 SignalR 客户端@kabaehr 提到的。到目前为止,SignalR 客户端本质上相当简单。

export class SignalRClient {

public connection = undefined;
private running: boolean = false;

public getOrCreateHub(hubName: string) {
hubName = hubName.toLowerCase();
if (!this.connection) {
this.connection = jQuery.hubConnection("https://myhost:myport");
}

if (!this.connection.proxies[hubName]) {
this.connection.createHubProxy(hubName);
}

return this.connection.proxies[hubName];
}

public registerCallback(hubName: string, methodName: string, callback: (...msg: any[]) => void,
startIfNotStarted: boolean = true) {

var hubProxy = this.getOrCreateHub(hubName);
hubProxy.on(methodName, callback);

//Note: Unlike C# clients, for JavaScript clients, at least one callback
// needs to be registered, prior to start the connection.
if (!this.running && startIfNotStarted)
this.start();
}

start() {
const self = this;
if (!self.running) {
self.connection.start()
.done(function () {
console.log('Now connected, connection Id=' + self.connection.id);
self.running = true;
})
.fail(function () {
console.log('Could not connect');
});
}
}
}

这里需要注意的一件重要事情是,对于 JavaScript SignalR 客户端,我们需要在启动连接之前注册至少一个回调方法。

有了这样的客户端代理,您可以按如下方式使用它。虽然下面的代码示例一般使用aurelia-framework,但是attached()中的SignalR部分与Aurelia无关。

import {autoinject, bindable} from "aurelia-framework";
import {SignalRClient} from "./SignalRClient";

@autoinject
export class SomeClass{

//Instantiate SignalRClient.
constructor(private signalRClient: SignalRClient) {
}

attached() {
//To register callback you can use lambda expression...
this.signalRClient.registerCallback("notificationHub", "somethingChanged", (data) => {
console.log("Notified in VM via signalr.", data);
});

//... or function name.
this.signalRClient.registerCallback("notificationHub", "somethingChanged", this.somethingChanged);
}

somethingChanged(data) {
console.log("Notified in VM, somethingChanged, via signalr.", data);
}
}

这是解决方案的关键。对于与启用 CORS 相关的部分,问题中已经提到了。欲了解更详细的信息,您可以引用以下链接:

关于javascript - 无法使 SignalR、Web API 和 SystemJS 一起工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39012946/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com