5 messaggi dal 27 luglio 2009
Ciao a tutti.
Ho un problema che non riesco a risolvere.
Da una mia applicazione ASP.Net 3.5 ho necessità di invocare dei web service di terze parti. Ho generato le classi proxy con il wizard disponibile in VS2008, tuttavia ho necessità di aggiungere un soap header particolare ad alcune chiamate che vengon fatte verso questi web service.
Purtroppo l'header non è definito nel wsdl, quindi il tool di VS2008 non crea automaticamente delle classi per gestire questo header.
Esiste un modo per aggiungere un soap header alla chiamata verso i web service, nonostante nel wsdl non ci sia menzione a tale header?

Ho provato a guardare in msdn ma sembra esserci la possibilità di gestire solo il caso opposto, ovvero lato server gestire soap header inviati dal client anche se non previsti...

Qualcuno sa darmi qualche idea?
Se ho ben capito la tua esigenza devi creare una SoapExtension e relativi SoapExtensionAttribute.
Vedo di postarti di seguito un po' di codice completo che, a titolo d'esempio, ti consenta di gestire l'autenticazione.
Definiamo le credenziali (username/password):
public class SecureWebServiceCredentials : SoapHeader
{
    public SecureWebServiceCredentials() { }
    public SecureWebServiceCredentials(string username, string password)
    {
        Username = username;
        Password = password;
    }

    private string _username = string.Empty;
    public string Username
    {
        get { return _username; }
        set { _username = value; }
    }

    private string _password = string.Empty;
    public string Password
    {
        get { return _password; }
        set { _password = value; }
    }
}

Nota che SecureWebServiceCredentials deriva da SoapHeader.

Ora formalizziamo l'interfaccia che dovranno esporre i webservice per supportare l'autenticazione:
public interface ISecureWebService
{
    string Username { get; }
    string Password { get; }
    bool Authenticate(SecureWebServiceCredentials credentials);        
}

e prepariamo una classe di base (abstract) per i nostri Web Service protetti:
public abstract class SecureWebService : WebService, ISecureWebService
{
    public SecureWebServiceCredentials Credentials;
    public abstract string Username { get; }
    public abstract string Password { get; }
    public virtual bool Authenticate(SecureWebServiceCredentials credentials)
    {
        return (credentials.Username.Equals(Username) && credentials.Password.Equals(Password));
    }
}

Creiamo l'estensione SOAP ed il relativo attributo:
public class SecureWebServiceCredentialsExtension : SoapExtension
{
    public override void ProcessMessage(SoapMessage message)
    {
        if (message.Stage == SoapMessageStage.AfterDeserialize)
        {
            // il web service espone l'interfaccia ISecureWebService?
            if (!(((SoapServerMessage)message).Server is ISecureWebService))
                return;
            ISecureWebService server = (ISecureWebService)((SoapServerMessage)message).Server;

            // cerco e verifico le credenziali tra le intestazioni SOAP:
            foreach (SoapHeader header in message.Headers)
            {
                if (header is SecureWebServiceCredentials)
                {
                    SecureWebServiceCredentials credentials = (SecureWebServiceCredentials)header;
                    if (server.Authenticate(credentials))
                        return;
                    break;
                }
            }
            // credenziali non trovate o autenticazione fallita:
            throw new SoapException("Unauthorized", SoapException.ClientFaultCode);
        }
    }

    public override object GetInitializer(Type type)
    {
        return GetType();
    }

    public override object GetInitializer(LogicalMethodInfo info, SoapExtensionAttribute attribute)
    {
        return null;
    }

    public override void Initialize(object initializer) { }
}

[AttributeUsage(AttributeTargets.Method)]
public class SecureWebServiceCredentialsExtensionAttribute : SoapExtensionAttribute
{
    private int _priority = 1;
    public override int Priority
    {
        get { return _priority; }
        set { _priority = value; }
    }

    public override Type ExtensionType
    {
        get { return typeof(SecureWebServiceCredentialsExtension); }
    }
}

Ora abbiamo tutto quel che ci serve per esporre e consumare web service che supportino l'autenticazione; ad esempio un semplice web service sicuro potrebbe essere definito come:
[WebService]
public class MyService : SecureWebService
{
    public string Username
    {
        get { return "pippo"; }
    }
    public string Password
    {
        get { return "pluto"; }
    }

    [WebMethod]
    [SecureWebServiceCredentialsExtension]
    [SoapHeader("Credentials")]
    public string HelloWorld()
    {
        return "Hello world!";
    }
}

Ed il realtivo proxy:
[WebServiceBinding]
public class LoginServiceProxy : SoapHttpClientProtocol
{
    private static readonly string ServiceUrl = "http://www.miosito/MyService.asmx";
    private static readonly SecureWebServiceCredentials ServiceCredentials = new SecureWebServiceCredentials("pippo", "pluto");

    public LoginServiceProxy() : this(ServiceUrl) { }    
    public LoginServiceProxy(string url) : this(url, ServiceCredentials) { }    
    public LoginServiceProxy(string url, SecureWebServiceCredentials credentials)
    {
        Url = url;
        CredentialsValue = credentials;
    }

    private SecureWebServiceCredentials _credentialsValue;
    public SecureWebServiceCredentials CredentialsValue
    {
        get { return _credentialsValue; }
        set { _credentialsValue = value; }
    }

    [SoapHeaderAttribute("CredentialsValue")]
    [SoapDocumentMethodAttribute(Use = SoapBindingUse.Literal, ParameterStyle = SoapParameterStyle.Wrapped)]
    public string HelloWorld()
    {
        object[] results = Invoke("HelloWorld", new object[] {  });
        return (bool)results[0];
    }
}

Ovviamente il mio esempio fa il doppio di quello che serve a te (nel tuo caso basta la parte relativa al proxy, senza tutto quel che riguarda la creazione del servizio) ma credo che sia utile per avere il quadro completo sull'uso delle estensioni SOAP.

HTH

PS: ho adattato al volo del codice esistente, spero che quanto postato almeno compili

Matteo Casati
GURU4.net

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.