将Silverlight客户端连接到SignalR服务器

时间:2014-09-26 19:26:25

标签: c# asp.net silverlight client-server signalr

我一直在努力解决这个问题,所以真的希望有人有一些见解。

我有一个运行/托管我的signalR服务器的控制台应用程序 我已经使用web(javascript)客户端和Windows窗体客户端成功连接到它,完全没有问题。

但是对于我的生活,我无法让Silverlight客户端连接到它。最初我得到了一个

' System.Security.SecurityException'发生在Microsoft.Threading.Tasks错误

on

等待Connection.Start();

我设法通过使用随机线程中找到的代码强制发送clientaccesspolicy文件来解决这个问题。

THREAD

然而,连接仍未建立。状态通过连接,断开连接,连接关闭。

我最终知道这为什么不能奏效。任何输入都表示赞赏。代码如下。

MainPage.xaml.cs
public partial class MainPage : UserControl
{
    private SignalRClient client;

    public MainPage()
    {
        InitializeComponent();

        dataGrid1.ItemsSource = new ItemsCollection();

        client = new SignalRClient();
        client.RunAsync();

        Debug.WriteLine("Init Done");
    }
}

-

SignalRClient.cs
public class SignalRClient
{
    private HubConnection Connection { get; set; }
    private IHubProxy HubProxy { get; set; }

    const string url = "http://localhost:8080/";

    public SignalRClient()
    {

    }

    public async void RunAsync()
    {
        Connection = new HubConnection(url, useDefaultUrl: true);
        Connection.Closed += Connection_Closed;
        Connection.StateChanged += ConnectionDidSomething;

        HubProxy = Connection.CreateHubProxy("TickerHub");
        HubProxy.On<string>("receiveAllData", data => Debug.WriteLine("RECDATA={0}", data));

        try
        {
            await Connection.Start();
        }
        catch (HttpClientException e)
        {
            Debug.WriteLine("Unable to connect to server.1 {0}", e.Message);
            return;
        }
        catch (HttpRequestException e)
        {
            Debug.WriteLine("Unable to connect to server.2 {0}", e.Message);
            return;
        }
    }

-

Server
class Program
{
    static void Main(string[] args)
    {            
        string url = "http://localhost:8080/";
        using (WebApp.Start(url))
        {
            Console.WriteLine("SignalR server running on {0}", url);
            Console.ReadLine();
        }            

        Console.ReadLine();
    }
}

class Startup
{
    public void Configuration(IAppBuilder app)
    {
        Console.WriteLine("Configuration");

        //Tried this approach too
        /*app.Map("/signalr", map =>
        {                
            map.UseCors(CorsOptions.AllowAll);
            var hubConfiguration = new HubConfiguration
            {
                EnableJSONP = true
            };
            map.RunSignalR(hubConfiguration);
        });*/

        app.UseCors(CorsOptions.AllowAll);
        app.MapSignalR<ClientAccessPolicyConnection>("/clientaccesspolicy.xml");
    }
}

-

TickerHub.cs
public class TickerHub : Hub
{
    public override Task OnConnected()
    {
        string connectionID = Context.ConnectionId;
        Console.WriteLine("New Connection:" + connectionID);

        InitNewClient(connectionID);

        return base.OnConnected();            
    }

    //send all data to newly connected client
    public void InitNewClient(string connectionID)
    {
    }

    //client requested all data
    public void GetAllData()
    {
        Console.WriteLine("Get Data Triggered");         

        Clients.All.receiveAllData("TESTING123");
    }

}

1 个答案:

答案 0 :(得分:3)

我明白了!希望这有助于将来的某个人。

非常简单。这是您在启动类配置方法中需要的。 下面是发送clientaccesspolicy.xml所需的代码。

class Startup
{
    public void Configuration(IAppBuilder app)
    {
        // Branch the pipeline here for requests that start with "/signalr"
        app.Map("/signalr", map =>
        {
            // Setup the CORS middleware to run before SignalR.
            // By default this will allow all origins. You can 
            // configure the set of origins and/or http verbs by
            // providing a cors options with a different policy.
            map.UseCors(CorsOptions.AllowAll);
            var hubConfiguration = new HubConfiguration
            {
                // You can enable JSONP by uncommenting line below.
                // JSONP requests are insecure but some older browsers (and some
                // versions of IE) require JSONP to work cross domain
                EnableJSONP = true
            };
            // Run the SignalR pipeline. We're not using MapSignalR
            // since this branch already runs under the "/signalr"
            // path.
            map.RunSignalR(hubConfiguration);
        });

        app.UseCors(CorsOptions.AllowAll);
        app.MapSignalR<ClientAccessPolicyConnection>("/clientaccesspolicy.xml");
    }
}

-

public class ClientAccessPolicyConnection : PersistentConnection
{
    public override Task ProcessRequest(Microsoft.AspNet.SignalR.Hosting.HostContext context)
    {
        string[] urlArray = context.Request.Url.ToString().Split('/');

        string path = urlArray[urlArray.Length - 1];

        if (path.Equals("clientaccesspolicy.xml", StringComparison.InvariantCultureIgnoreCase))
        {
            //Convert policy to byteArray
            var array = Encoding.UTF8.GetBytes(ClientAccessPolicy);
            var segment = new ArraySegment<byte>(array);

            //Write response
            context.Response.ContentType = "text/xml";
            context.Response.Write(segment);

            //Return empty task to escape from SignalR's default Connection/Transport checks.
            return EmptyTask;
        }

        return EmptyTask;
    }

    private static readonly Task EmptyTask = MakeTask<object>(null);

    public static Task<T> MakeTask<T>(T value)
    {
        var tcs = new TaskCompletionSource<T>();
        tcs.SetResult(value);
        return tcs.Task;
    }

    public static readonly string ClientAccessPolicy =
        "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
                + "<access-policy>"
                   + "<cross-domain-access>"
                     + "<policy>"
                       + "<allow-from http-request-headers=\"*\">"
                            + "<domain uri=\"*\"/>"
                       + "</allow-from>"
                       + "<grant-to>"
                            + "<resource path=\"/\" include-subpaths=\"true\"/>"
                       + "</grant-to>"
                    + "</policy>"
                + "</cross-domain-access>"
              + "</access-policy>";
}