.net Web APIコントローラーアクション内からクライアントメソッドを呼び出そうとしています。
これはできますか?
私が探しているものに近いものを見つけることができる唯一の投稿はこれです:
SignalR +アクションメソッドを介してハブにメッセージを投稿する
そこには、GlobalHost.ConnectionManager.GetHubContextを使用してasp.net MVCコントローラーアクション内からメッセージが送信されます。
Web APIアクション内でそれを試してもエラーはスローされませんが、メソッド「methodInJavascript」がクライアント側で呼び出されることはありません。
Public ActionResult MyControllerMethod()
{
var context = GlobalHost.ConnectionManager.GetHubContext<MyHub>();
context.Clients.All.methodInJavascript("hello world");
// or
context.Clients.Group("groupname").methodInJavascript("hello world");
}
そのアクション内にブレークポイントを設定すると、コードに到達して実行されていることがわかります。ただし、JavaScriptクライアント側では何も起こりません。
どうして? Web APIはフードの下で非常に異なるので、これは機能しませんか?他の誰かがそれを試し、成功しましたか?
ハブの「内」から「methodInJavascript」を呼び出すと、完全に機能します。 .net Web APIコントローラーアクション内から呼び出された場合は機能しません。
UPDATE:
この問題を調査した後、解決策はありません。私はこのような例に欠けているものがあると仮定することができます ASP.NET MVC 4のSignalRで通過しないサーバーからクライアントへのメッセージ そしてこれ WebAPIコントローラーの問題からSignalRハブを呼び出す HubContextなどからの呼び出しを可能にする追加の構成ステップがあるかもしれません。私が最初にここに投稿したコードは、これらの例に表示されているものに似ていますが、いかなる形でも欠陥があることは実証されていません。誰でもコードの欠陥を見ることができますか? htmlからの呼び出しは機能します。私は自分のアプリで広範囲にそれを行い、問題を経験することはありません。 APIコントローラーの動作でHubContextからの呼び出しを見たことはありません。エラーなし。クライアントに結果がありません。
SOLVED(種類):
上記のコードは、公開されるとそのまま機能します。ただし、localhost経由のVisual Studio開発環境では機能しません。エラーはありませんが、クライアント側で結果はありません。 Web上の実サーバーにコードをそのまま公開することは実際に機能します。違いがあるとは思わなかったので、試したことはありません。ローカルで動作しなかった場合、公開された動作しないだろうと考えました。現在ライブで動作していますが、なぜ開発環境でローカルホスト経由で動作しないのか疑問に思っています。ブレークポイントなどでローカルにテストすることはできません。
そのシグナル仮想ディレクトリだと感じています。ローカルで実行する場合と公開する場合で何かが異なります。よくわかりませんが、 http://www.bitwisejourneys.com/signalr-hosting-in-iis-a-nasty-gotcha/ のような投稿がたくさんあります。今すぐ読んで、ローカルでも公開でも機能する方法があるかどうかを確認してください。
数日前に同じ問題に遭遇しました。解決策を見つけて解決するまでに2日かかりました。いくつかの深刻な調査の後、問題の根本原因は、私がカスタムで設定したシグナル依存リゾルバでした。
最後に私は このリンク を見つけました、そしてそれはこれを言っていました:
DependencyResolverの置き換え
GlobalHost.DependencyResolverを設定することにより、DependencyResolverを変更して、選択したDIコンテナーを使用できます。
注:PreApplicationStartのグローバルリゾルバーをオーバーライドしないでください。動作しません。または、時々しか動作しません。 PostApplicationStart(WebActivatorを使用)またはGlobal.asaxで実行します。
ここで重要な場所はメモです。もちろん、signalr 2.0の後、このドキュメントは推奨されなくなりました。そこで、ここでいくつかを新しいSignalR APIと組み合わせました。新しいSignalR APIでは、WebActivatorExを使用しなくなりました。 WebActivatorではなくOwinStartupが推奨されます。
[Assembly: OwinStartupAttribute(typeof(YourNamespace.Startup))]
namespace YourNamespace
{
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
//IoC container registration process
UnityConfig.RegisterComponents();
UnityConfig.Container.RegisterType<AHub, AHub>();
HubConfiguration config = new HubConfiguration();
config.EnableJavaScriptProxies = true;
//You should remove your dependency resolver code from here to Global.asax Application_Start method. Before setting the MVC properties.
//config.Resolver = new SignalrDefaultDependencyResolver(UnityConfig.Container); // your dependency resolver
//
app.MapSignalR(config);
}
}
}
そしてあなたのglobal.asaxで
namespace YourNamespace
{
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
//Here your SignalR dependency resolver
GlobalHost.DependencyResolver = new SignalrDefaultDependencyResolver(UnityConfig.Container);
//other settings goes on
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
}
実際の問題を明らかにするために、ここにすべてのコードを送信したくありません。
だから私にとっては今のところすべてがうまく動作します。依存性注入も機能します。しかし、悪い部分は、私がデビッド・ファウラーが「設計による」と言っていたところを検索したことです。このデザインは本当に必要なのか、間違いなのかと思い始めました。
同じ問題を研究する他の誰かに役立つことを願っています。
私も同じ問題を抱えていましたが、IoCに関連しています(ninjectやcastleなど)。 IoCマネージャーにグローバル依存関係リゾルバーを設定すると、SignalR内部パイプライン解決も置き換えられます。これにより、SingleTonクライアントハブが正常に動作しなくなります。
サーバーハブをIoCで処理するだけで解決しました。以下のコードにはSignalHubActivatorが必要です(インターネットで見つけることができます)
これで、GlobalHost.ConnectionManager.GetHubContextは単一のインスタンスを返し、クライアントメソッドは再び正しく呼び出されます!
//configuration.Resolver = signalrDependency ; dont, this will cause GlobalHost.ConnectionManager to be intercepted by Castle
configuration.Resolver.Register(typeof(IHubActivator),
() => new SignalHubActivator(container));