2016-08-18 10 views
1

JavaScript(Aurelia)クライアント(WebApp)に通知する通知APIをWeb API上に構築しようとしています。 My Web APIとWebAppは異なるドメインにあります。SignalR、Web API、およびSystemJSを連携させることができません

私はシンプルNotificationHubを持っている:

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

次のように私は、Web APIのStartupでSignalRを設定しています:私のWebAppので

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サイトからsignalr/hubsにアクセスしようとしていますAPIは次のとおりです。

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

I hav

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

これらの構成にもかかわらず、私はまだ持っている以下のような問題点:eはまた私のconfig.jsmetaセクションを追加し

  1. 要求をsignalr/hubsため、WebAppのから、https://localhost:44304/signalr/hubs.jsとして作られた、とHTTP 404されます返されます。 https://localhost:44304/signalr/hubsを参照すると、hubsスクリプトが返されます。 $.connection("https://localhost:44304/signalr").start()
  2. 、私は次のエラーが発生します:

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の設定を使用して 、および@kabaehrによって提案gist私は今、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(); 
     }); 
    } 
} 

次のように私はStartupでそれを使用しています:

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を明示的にインポートする必要はないと仮定しています。

+0

あなたの起源はhttps'それはそう '使用されていませんか?この問題を回避するには、最初に '' * ''を試してみてください。 –

+0

@ MarkC。ご意見ありがとうございます。私は '' * ''で試してみましたが、 '' SystemJS'が '' signal_/hubs'の最後に '.js'を追加するので、実際に動作しているかどうかはわかりません。 404 '。私は何とか先に処理する必要があると思いますが、どうしたらよいか分かりません。 –

+0

システムのjsには、https://github.com/systemjs/plugin-textのような「.js」の追加を防ぐことができるプラグインがいくつかありますが、これが問題であるかどうかはわかりません。 – kabaehr

答えて

0

これは私の調査結果とその問題を解決するためのものです。

まず、signalr/hubsは、サーバーサイドコードから自動生成されたプロキシです。独自のSignalRプロキシクライアントを作成できる場合は、そのプロキシを使用する必要はありません。以下は、@ kabaehrが言及したgistに基づいて作成された、このような単純なSignalRクライアントの1つです。 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を有効にすることに関連する部分については、既にその質問で言及されている。より詳細な情報については、あなたがこれらのリンクを参照してください可能性があります

関連する問題