简体   繁体   中英

Using websockets in classic asp.net forms application

I need to add websocket functionality to legacy asp.net webforms application (just one simple long time workflow converted from old applet functionality).

I naively tried to just add websocket handler to aspx page:

        public override void ProcessRequest(HttpContext context)
        {
            if (context.IsWebSocketRequest)
            {
                context.AcceptWebSocketRequest(HandleWebSocket);
            } else
            {
                base.ProcessRequest(context);
            }
        }

and enable websocket on the IIS: 在此处输入图像描述 Then try: var ws = new WebSocket("ws://localhost/APP/Page.aspx"); but this does not seam to work.

Not sure if this is at all possible?

Do I miss something about configuration or implementation? I could put websocket on separate application/server but would prefer to keep it in one place with access to same session object.

It should be possible to handle a web socket connect in a classic ASP.NET Forms application. The tools are available on HttpContext and you basically have the correct idea.

I think the issue is that you are trying to invoke it from an aspx page and not just using a generic IHttpHandler . IIS runs specific processing pipelines based upon the file extension. Aspx is rather specialized to trying to render an HTML page, so while it might be possible to reconfigure IIS to allow websockets to interact with ASPX pages, it is much easier to just use a generic ashx handler.

You can create a handler by going to the "Add Item" dialog in Visual Studio突出显示“通用处理程序”条目的 Visual Studio 的“添加项目”对话框

At this point, you would just implement your websocket logic in your handler code. I'm putting in a simple echo from this as.net sample just to demonstrate.

public class MyHandler : IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        if (context.IsWebSocketRequest)
        {
            context.AcceptWebSocketRequest(EchoWebSocket);
        }
    }

    private async Task EchoWebSocket(AspNetWebSocketContext socketContext)
    {
        var buffer = new byte[1024 * 4];
        var result = await socketContext.WebSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);

        while (!result.CloseStatus.HasValue)
        {
            await socketContext.WebSocket.SendAsync(new ArraySegment<byte>(buffer, 0, result.Count), result.MessageType, result.EndOfMessage, CancellationToken.None);
            result = await socketContext.WebSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
        }

        await socketContext.WebSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
}

You should now be able to connect to the websocket. Note the usage of wss rather than ws . The setup I tested with requires the secure version (wss). Use whatever is relevant for the application you are working on.

// Replace with port/path to your handler.
var ws = new WebSocket("wss://localhost:44336/MyHandler.ashx");

ws.onmessage = function(evt) { 
    console.log(evt); 
};

ws.send("Hello, World!");

And you should see output similar to this: 带有上述示例 javascript 输出的 Chrome 开发人员控制台。

Note: I generally wouldn't recommend trying to access Session data from the websocket handler. Your session may expire outside the timeframe of the websocket's lifespan. You would probably want to use some other mechanism to persist state between the socket and the rest of the pages (potentially a database or the application-level cache, which you can access from socketContext.Cache in the example above.

Edit: Added an example of using session value on socket initialization. Per your comment, if you want to use session values during the initialization of a websocket (which should be a safe operation), then your handler just needs to implement IRequiresSessionState and needs to add a little extra syntax to pass the session value into the accept handler.

public class MyHandler : IHttpHandler, IRequiresSessionState
{
    public void ProcessRequest(HttpContext context)
    {
        if (context.IsWebSocketRequest)
        {
            var sessionValue = context.Session["session_key"] as string;

            context.AcceptWebSocketRequest(async (socketContext) =>
            {
                await SetupWebSocket(socketContext, sessionValue);
            });
        }
    }

    private async Task SetupWebSocket(AspNetWebSocketContext socketContext, string sessionValue)
    {
        // Handle socket as before, but 'sessionValue' is now available for use.
    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM