0
\$\begingroup\$

I have got two generic methods to call against a service. Depending on call, some methods return an object (passed in params), some don't (void). Can this be further improved? I have got to this point after refactoring a lot and removing anything which was repeated.

private static TResponse ServiceCall<TObjectToPass, TResponse>(
    Func<TObjectToPass, TResponse> func, 
    TObjectToPass obj)
{
    var temp = ServicePointManager.ServerCertificateValidationCallback;
    ServicePointManager.ServerCertificateValidationCallback += 
        (sender, certificate, chain, errors) => true;

    var r = func(obj);

    ServicePointManager.ServerCertificateValidationCallback = temp;

    return r;
}

private static void ServiceCall<TObjectToPass>(
    Action<TObjectToPass> func, 
    TObjectToPass obj)
{
    var temp = ServicePointManager.ServerCertificateValidationCallback;
    ServicePointManager.ServerCertificateValidationCallback += 
        (sender, certificate, chain, errors) => true;

    func(obj);

    ServicePointManager.ServerCertificateValidationCallback = temp;
}
\$\endgroup\$
3
  • \$\begingroup\$ Is the intent of your ServerCertificateValidationCallback delegate to always validate certificates regardless of the certificate? That's not really what you're doing there. \$\endgroup\$ Commented Apr 28, 2016 at 15:49
  • 1
    \$\begingroup\$ You don't really need to pass in obj separately, as it can just be part of the action/func that gets injected. \$\endgroup\$ Commented Apr 28, 2016 at 17:24
  • \$\begingroup\$ @CodingGorilla yes. Regardless, it needs to return true. \$\endgroup\$
    – Yahya
    Commented Apr 29, 2016 at 8:17

1 Answer 1

1
\$\begingroup\$
  1. Keep the reference to your callback, so you can remove it when it is no longer needed :

    // add this to the class
    private static readonly RemoteCertificateValidationCallback IgnoreValidation =
        (sender, certificate, chain, errors) => true;
    
    // inside your methods
    ServicePointManager.ServerCertificateValidationCallback += IgnoreValidation;
    // do stuffs
    ServicePointManager.ServerCertificateValidationCallback -= IgnoreValidation;
    
  2. Consider switch the order of your parameter. TObjectToPass is the key generic parameter in both method, yet its definition is unclear until the 2nd parameter is passed or unless you specify in ServerCall<__HERE__>(... or ServerCall((___HERE x) => .... By keep it on the 2nd place, you penalize yourself by not taking advantage of intellisense :

    // compiler has no idea what is x
    ServiceCall(x => x
    
    // compiler is happy to tell you what x can do
    ServiceCall(new { A = 'a' }, x => Console.WriteLine(x.A
    

    private static TResponse ServiceCall<TObjectToPass, TResponse>(
    TObjectToPass obj,
    Func<TObjectToPass, TResponse> func)
    {
        ServicePointManager.ServerCertificateValidationCallback += IgnoreValidation;
        var response = func(obj);
        ServicePointManager.ServerCertificateValidationCallback -= IgnoreValidation;
    
        return response;
    }
    
    private static void ServiceCall<TObjectToPass>(
        TObjectToPass obj,
        Action<TObjectToPass> action)
    {
        ServicePointManager.ServerCertificateValidationCallback += IgnoreValidation;
        action(obj);
        ServicePointManager.ServerCertificateValidationCallback -= IgnoreValidation;
    }
    
\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.