在c#

时间:2018-08-29 13:54:16

标签: c# session httpclient

我有一个使用HttpClient的Webcrawler应用程序,以执行一些请求。

当我启动应用程序时,将初始化一个类似于以下内容的新HttpClient:

public static void ResetHttpClient()
{
    Client = new HttpClient();
}

应用程序重新启动后,该应用程序必须重新登录,这由于每小时n次登录的限制而导致麻烦。

因此,我从应用程序的另一部分复制了一个函数,该函数序列化了一个列表>,并将此列表保存到文件中。

我修改了该功能,以便使用HttpClient对其进行测试。 我的意图是保存HttpClient,然后在程序启动/重新启动时保存HttpClient并继续“会话”。 保存功能的代码(我只用一个列表就知道列表很丑):

// SAVE
(HttpClient client, DateTime clientCreationDate) httpClientSaveData = 
    new ValueTuple<HttpClient, DateTime>(Client, ClientCreatedDate);
FileStream stream = new FileStream(@"HttpClient.dat", FileMode.Create);
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, httpClientSaveData);
stream.Close();

使用上面的代码,我收到以下错误消息:

  

System.Runtime.Serialization.SerializationException:程序集'System.Net.Http中的'Type'System.Net.Http.HttpClient',Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b03f5f7f11d50a3a'未标记为可序列化。'

现在我的问题是:是否可以通过保存cookie来保存/加载“会话”? 可行的方法是什么?

2 个答案:

答案 0 :(得分:0)

发生错误是因为您正在尝试序列化不具有[Serializable]属性的对象。因为它是框架类,所以也不能添加它。

HttpClient对象将被重用,这只是您的应用程序中如何使用的问题。通常,您会将框架HttpClient包装在执行所需特定操作的类中,并将其用作Singleton。

看起来这几乎是您正在做的事情,因此问题更多的是您的应用程序频繁启动和停止,这导致重新创建对象。

如果您想在维持状态的同时定期运行某些程序,那么最好的工具是Windows Service

如果要基于在自己的Web应用程序中收到另一个请求来触发请求,则应该使用具有Singleton范围的Dependency Injection。只要启用了应用程序池,这将使对象保持活动状态。如果需要,可以增加IIS中的空闲时间。我认为默认情况下是15分钟,这将保证每小时不超过4次登录。

编辑:

由于主要问题似乎在于开发和测试期间,因此您应该可以作弊。使用Fiddler之类的代理,您可以记录手动登录所采取的步骤。您需要注意的是Http Headers。大多数身份验证/会话类型数据将位于Cookie标头或Authorization标头中。也可能有诸如X-Session-ID之类的标头。成功登录后,您应该能够手动复制标题,然后将其粘贴到您的代码中。像Postman这样的客户端在这里可以非常有用,可以准确地确定需要哪些标头。

您的代码将如下所示:

public static void ResetHttpClient()
{
    Client = new HttpClient();

    if (isDevelopment) // however you determine it
    {
         Client.DefaultRequestHeaders
               .TryAddWithoutValidation("Authorization", "Bearer hhxcshRT43bhJHjh53hkjhbhvghf54g5hbhkghfdUGUKGYFDJihu5");
         Client.DefaultRequestHeaders
               .TryAddWithoutValidation("Cookie", "SessionID=36dab-3545-adef");
    }
}

答案 1 :(得分:0)

对我有用的解决方案是将CookieContainer保存到文件并加载。为此,我创建了以下两个函数:

/// <summary>
/// this function loads the CookieContainer that contains the Session Cookies
/// </summary>
public static void LoadHTTPClient()
{
    CookieJar = new CookieContainer();
    if (File.Exists(@"ClientSessionCookies.dat"))
    {
        // LOAD
        FileStream inStr = new FileStream(@"ClientSessionCookies.dat", FileMode.Open);
        BinaryFormatter bf = new BinaryFormatter();
        CookieJar = bf.Deserialize(inStr) as CookieContainer;
        inStr.Close();
    }
    var handler = new HttpClientHandler
    {
        CookieContainer = CookieJar,
        UseCookies = true,
    };
    Client = new HttpClient(handler);
}

/// <summary>
/// this function saves the sessioncookies to file
/// </summary>
/// <param name="CookieJar"></param>
public static void SaveHTTPClient(CookieContainer CookieJar)
{
    // SAVE client Cookies
    FileStream stream = new FileStream(@"ClientSessionCookies.dat", FileMode.Create);
    BinaryFormatter formatter = new BinaryFormatter();
    formatter.Serialize(stream, CookieJar);
    stream.Close();
}

thx @AlexK和@ADyson作为提示

  

我可以想象登录过程可能会发布一个cookie,以期望浏览器将其存储以用于将来的请求。这就是大多数基于浏览器的登录系统的工作方式。您可能可以掌握它,然后重新使用它,直到过期为止。恐怕我不知道该怎么做,但是,如果您搜索使用C#HttpClient使用cookie,那么您可能会走上正确的道路。 – ADyson

-

  

Cookies(通过HTTP标头)是一种机制,通过该机制服务器可以将HTTP请求与会话进行协调,例如,可以通过HttpClient读取/写入。 stackoverflow.com/questions/13318102/…– Alex K。