Firstly, the error message I get is as follows: Internal handler not installed
I am writing a special message handler to handle authentication cookie timeouts for my API. For example, if my code base makes an API call and, in turn, receives 401, then it must repeat the login URL in order to receive an updated cookie. I planned to do it as follows:
public class CkApiMessageHandler : DelegatingHandler { private readonly string _email; private readonly string _password; private const string _loginPath = "Account/Login"; public CkApiMessageHandler(string email, string password) { _email = email; _password = password; //InnerHandler = new HttpControllerDispatcher(null); } protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { var response = await base.SendAsync(request, cancellationToken); if(response.StatusCode == System.Net.HttpStatusCode.Unauthorized) { Logging.Logger.LogInformation("Authentication cookie timed out"); var baseAddress = request.RequestUri.Host; var loginPath = baseAddress + _loginPath; var originalRequest = request; var loginRequest = new HttpRequestMessage(new HttpMethod("POST"), loginPath); var dict = new Dictionary<string, string>(); dict.Add("Email", _email); dict.Add("Password", _password); var form = new FormUrlEncodedContent(dict); loginRequest.Content = form; loginRequest.Headers.Clear(); foreach(var header in originalRequest.Headers) { loginRequest.Headers.Add(header.Key, header.Value); } var loginResponse = await base.SendAsync(loginRequest, cancellationToken); if (loginResponse.IsSuccessStatusCode) { Logging.Logger.LogInformation("Successfully logged back in"); return await base.SendAsync(originalRequest, cancellationToken); } else { Logging.Logger.LogException(new Exception("Failed to log back in"), "Could not log back in"); } } return response; } }
I am converting an old service that is used for direct access to a database to a service that accesses the web api, and I am trying to do this without changing any of the consumers of this class. Therefore, a strange handler. The following is an example of a method from a service class.
public void UpdateClientInstallDatabaseAndServiceData(string dbAcronym, string clientVersion, string clientEnginePort, Guid installationId, string sqlserver) { var dict = new Dictionary<string, string>(); dict.Add("dbAcronym", dbAcronym); dict.Add("clientVersion", clientVersion); dict.Add("clientEnginePort", clientEnginePort); dict.Add("desktopClientId", installationId.ToString()); dict.Add("sqlServerIp", sqlserver); var form = new FormUrlEncodedContent(dict); _client.PostAsync(_apiPath + "/UpdateClientInstallDatabaseAndServiceData", form); }
Thus, if the above code fails with error 401, the service will automatically log in and repeat the original code without requiring the service consumer to check the requests and go back. The consumer does not need to know that he is dealing with a web api.
My problem is that my message handler is waiting for an InnerHandler install, which requires an instance of the HttpConfiguration class. When I look at the specifications here , this seems to be some type of class used to configure the web api service. This is good, except that this code does not execute in api .. It runs in a Windows Forms application. A delegation handler is used in an HttpClient class such as ...
_client = new HttpClient(new CKEnterprise.Common.CkApiMessageHandler(email, password));
So my question is : How can I get this DelegatingHandler to do this work outside the context of the api web project context?
Performing an upgrade. It looks like I can just use the HttpClientHandler class https://blogs.msdn.microsoft.com/henrikn/2012/08/07/httpclient-httpclienthandler-and-webrequesthandler-explained/