【发布时间】:2021-10-15 02:02:27
【问题描述】:
我们有一个带有登录名的 ASP.NET 5 Web 服务器,它使用 HttpContext.Session.SetString 设置会话变量。那是以后用的。这工作得很好。
现在我们需要一个入口点,您可以在其中将所有信息发布到它需要的网络服务器(例如登录信息)以返回网站。到目前为止,这是可行的,但是在我们在 Window 中加载任何其他网站后,会话丢失了。
在客户端,我们使用 CefSharp 浏览器将数据发布到站点(如此处所述 Send POST data to URL with CefSharp C# )。 虽然我必须先打开地址然后发布到它。 在服务器端,我们得到这样的信息。
public IActionResult Entry(string id)
{
_logger.LogInformation("Entry");
_logger.LogInformation("Session1: " + HttpContext.Session.Id);
HttpContext.Session.SetString("test", "1");
return new EmptyResult();
}
[HttpPost]
public IActionResult Entry(string id, [FromBody]SomeClass request)
{
_logger.LogInformation("EntryPost");
_logger.LogInformation("Session1: "+ HttpContext.Session.Id);
process(request);
//(... set Session, create a Model and return a View)
打开站点进入“Entry”,然后帖子进入“EntryPost”。它们已经有不同的 SessionId,这并不是世界末日,但只要我们在 BrowserView 中单击一个按钮并加载一个新站点,Session 也会丢失。
我花了一些时间将每个 XML 的数据正确地发送到服务器,这部分工作没有问题。浏览器从该服务器保存 Cookie 通常没有问题,因为该网站通过上述登录页面正常工作。
我们通过重定向阅读了很多关于会话丢失的问题,因此我们将它们全部删除,这至少显示了没有会话丢失的初始站点,但在手动单击重新加载站点之后却没有。我们尝试了很多东西,但我们不知道会话为什么会中断。
如果有人有任何想法,请告诉我。
添加“简化”版本的浏览器代码:
public class HTML : Form
{
public ChromiumWebBrowser browser;
private static bool _init;
private void InitBrowser(string url)
{
if (!_init) {
CefSettings settings = new CefSettings() { PersistSessionCookies = true }; // One of the things we tried
_init = Cef.Initialize(settings);
}
if (browser == null && _init == true)
{
browser = new ChromiumWebBrowser(url);
this.Controls.Add(browser);
}
}
public void setAddress(string address)
{
if (address == "") address = "about:blank";
if (browser != null && browser.IsBrowserInitialized)
{
browser.Load(address);
}
else
{
InitBrowser(address);
}
}
public override bool EntryPost(SomeClass request)
{
string gciXML = XMLTools.Serialize(gci);
// setAddress("https://OurWebserver:44333/"); // Login Page, Website Works without problems
InitPost("https://OurWebserver:44333/Home/Entry/id", gciXML);
return true;
}
// Start Post functionality
private Queue<PostParams> _postParam = new Queue<PostParams>();
private class PostParams
{
public string url;
public string postData;
}
/// <summary>
/// HTML Post.
/// Standard .NET Browser uses the same function name
/// </summary>
/// <param name="url"></param>
/// <param name="postDataBytes"></param>
internal void Navigate(string url, byte[] postDataBytes)
{
IFrame frame = browser.GetMainFrame();
IRequest request = frame.CreateRequest();
request.Url = url;
request.Method = "POST";
request.InitializePostData();
var element = request.PostData.CreatePostDataElement();
element.Bytes = postDataBytes;
request.PostData.AddElement(element);
NameValueCollection headers = new NameValueCollection();
headers.Add("Content-Type", "application/xml");
headers.Add("Connection", "keep-alive");
request.Headers = headers;
frame.LoadRequest(request);
frame.GetTextAsync().ContinueWith(taskHtml =>
{
var html = taskHtml.Result;
Console.WriteLine("HTML:" + html);
});
string script = string.Format("document.documentElement.outerHTML;");
frame.EvaluateScriptAsync(script).ContinueWith(x =>
{
var response = x.Result;
if (response.Success && response.Result != null)
{
var fullhtml = response.Result;
Console.WriteLine("fullhtml:" + fullhtml.ToString());
}
}
);
}
private void Browser_FrameLoadEnd_InitPost(object sender, FrameLoadEndEventArgs e)
{
// TODO Browser sometimes adds "/" to the url. This basicly runs into endless loop, but it works with the example
if (browser.Address == _postParam.Peek().url)
{
browser.FrameLoadEnd -= Browser_FrameLoadEnd_InitPost;
if (_postParam != null && _postParam.Count > 0)
{
PostParams postObject = _postParam.Dequeue();
Navigate(postObject.url, Encoding.ASCII.GetBytes(postObject.postData));
// TODO repeat process if the queue isn't empty , works well for one Post Request for now
}
}
else
{
this.setAddress(_postParam.Peek().url);
}
}
private void Browser_IsBrowserInitializedChanged_InitPost(object sender, EventArgs e)
{
if (browser.IsBrowserInitialized)
{
browser.IsBrowserInitializedChanged -= Browser_IsBrowserInitializedChanged_InitPost;
this.setAddress(_postParam.Peek().url);
browser.FrameLoadEnd += Browser_FrameLoadEnd_InitPost;
}
}
/// <summary>
/// puts the url and postData in a Queue and keeps it there until the Post is done
/// </summary>
/// <param name="pUrl"></param>
/// <param name="pPostData"></param>
internal void InitPost(string pUrl, string pPostData)
{
bool empty = _postParam.Count == 0;
PostParams postObject = new PostParams() { url = pUrl, postData = pPostData };
_postParam.Enqueue(postObject);
if (empty)
{
// Decide what to do depending on the state of the browser
if (browser == null) setAddress(""); // starts Init process
if (!browser.IsBrowserInitialized)
{
browser.IsBrowserInitializedChanged += Browser_IsBrowserInitializedChanged_InitPost;
}
else
{
Browser_IsBrowserInitializedChanged_InitPost(null, null);
}
}
}
}
解释:
- EntryPost 曾在表单上从外部调用一次。
- InitPost 决定首先做什么,按需启动 init 进程。您可以在创建时为浏览器提供一个 url - 这就是我决定将它与 setAddress 结合起来的原因。
- PostUrl 已加载,我们等待 FrameLoadEnd 事件。
- Frame 加载完成后,将发送 Post 请求。
导航是从上面链接的 stackoverflow 页面复制而来的。我想我添加了 Connection 标头。 Iirc 它会自动发送一堆头信息。
【问题讨论】:
-
They already have different SessionIds, which isn't the end of the world实际上是。这意味着第二个操作启动了一个新会话,可能是因为它是一个新会话,从一个新选项卡或新浏览器实例开始。您此时所做的任何事情都会在新会话上运行。就任何 HTTP 服务器而言,CefSharp 都是浏览器 -
您有 CefSharp 问题,但没有 CefSharp 代码
-
@PanagiotisKanavos 你是对的。我添加了 CefSharp 代码。我想,由于正常的 LoginPage 工作正常,浏览器没有问题。但是当然还有很多其他代码可能会出现问题。 “这不是世界末日”我的意思实际上是,但我不知道这是问题根源的线索。
标签: c# asp.net .net asp.net-mvc