Question

Je suis en train de mettre en œuvre un UPnP MediaServer dans WCF. Je reçois lentement là-bas, mais maintenant je l'ai frappé un mur de briques. Je dois ajouter un préfixe à l'espace de noms ServiceContract. En ce moment, je donne les résultats suivants:

[ServiceContract(Namespace = "urn:schemas-upnp-org:service:ContentDirectory:1")]
public interface  IContentDirectory
{
    [OperationContract(Action = "urn:schemas-upnp-org:service:ContentDirectory:1#Browse")]
    void Browse(string ObjectID, string BrowseFlag, string Filter, ulong StartingIndex, ulong RequestedCount, string SortCriteria, out string Result, out ulong NumberReturned, out ulong TotalMatches, out ulong UpdateID);
}

Cette écoute les messages de savon corrects. Cependant, j'ai besoin du savon corps pour commencer

<u:Browse xmlns:u="urn:schemas-upnp-org:service:ContentDirectory:1">

et WCF est maintenant écoute:

<Browse xmlns="urn:schemas-upnp-org:service:ContentDirectory:1">

Comment puis-je obtenir là le préfixe? Est-ce que ça importe? Ou est-il une autre raison pour laquelle les paramètres ne sont pas passés dans la méthode browse?

UPDATE Voici quelques informations supplémentaires: Le message suivant est envoyé par un véritable point de contrôle UPnP. Les paramètres sont pas passé dans la méthode browse.

<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <To s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://XXXXX:8731/ContentDirectory</To>
    <Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">urn:schemas-upnp-org:service:ContentDirectory:1#Browse</Action>
  </s:Header>
  <s:Body>
      <u:Browse xmlns:u="urn:schemas-upnp-org:service:ContentDirectory:1">
         <ObjectID>0</ObjectID>
         <BrowseFlag>BrowseDirectChildren</BrowseFlag>
         <Filter>*</Filter>
         <StartingIndex>0</StartingIndex>
         <RequestedCount>15</RequestedCount>
         <SortCriteria />
      </u:Browse>
   </s:Body>
</s:Envelope>

Ceci est la demande qui est généré par le client de test WCF. Maintenant, les paramètres sont passés dans la méthode Parcourir:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <To s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://XXXXXX:8731/ContentDirectory</To>
    <Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">urn:schemas-upnp-org:service:ContentDirectory:1#Browse</Action>
  </s:Header>
  <s:Body>
    <Browse xmlns="urn:schemas-upnp-org:service:ContentDirectory:1">
      <ObjectID>0</ObjectID>
      <BrowseFlag>BrowseMetadata</BrowseFlag>
      <Filter>*</Filter>
      <StartingIndex>0</StartingIndex>
      <RequestedCount>0</RequestedCount>
      <SortCriteria i:nil="true" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" />
    </Browse>
  </s:Body>
</s:Envelope>
Était-ce utile?

La solution

Les deux demandes que vous avez montré (un par le point de contrôle UPnP et un par le client test WCF) sont pas équivalent . L'espace de noms des enfants de l'élément Parcourir dans la première (UPnP) est le vide ( « ») espace de noms, alors que dans la deuxième demande (WCF TC), il est « urn: schemas-upnp-org: Service: RépertoireContenu: 1 » - le préfixe vide est lié à l'espace vide, sauf si il est lié à un autre espace de noms, et il est rebond de la demande WCF, mais pas sur celle UPnP.

Maintenant, si vous voulez l'espace de noms des paramètres d'une opération soit différente de l'espace de noms de l'opération elle-même, vous devez utiliser un contrat de message - que vous obtiendrez la requête envoyée par WCF être équivalent ( Préfixe modulo) à la demande envoyée par le point de commande UPnP. Le code ci-dessous montre comment serait défini un contrat de message pour générer une demande équivalente à celle que vous avez montré pour le point de contrôle.

public class StackOverflow_2495195
{
    [MessageContract(WrapperName="Browse", WrapperNamespace="urn:schemas-upnp-org:service:ContentDirectory:1", IsWrapped=true)]
    public class BrowseRequest
    {
        [MessageBodyMember(Namespace = "", Order = 0)]
        public string ObjectID;

        [MessageBodyMember(Namespace = "", Order = 1)]
        public string BrowseFlag;

        [MessageBodyMember(Namespace = "", Order = 2)]
        public string Filter;

        [MessageBodyMember(Namespace = "", Order = 3)]
        public ulong StartingIndex;

        [MessageBodyMember(Namespace = "", Order = 4)]
        public ulong RequestedCount;

        [MessageBodyMember(Namespace = "", Order = 5)]
        public string SortCriteria;
    }

    [MessageContract(WrapperName = "BrowseResponse", WrapperNamespace = "urn:schemas-upnp-org:service:ContentDirectory:1", IsWrapped = true)]
    public class BrowseResponse
    {
        [MessageBodyMember(Namespace = "", Order = 0)]
        public string Result;

        [MessageBodyMember(Namespace = "", Order = 1)]
        public ulong NumberReturned;

        [MessageBodyMember(Namespace = "", Order = 2)]
        public ulong TotalMatches;

        [MessageBodyMember(Namespace = "", Order = 3)]
        public ulong UpdateID;
    }

    [ServiceContract(Namespace = "urn:schemas-upnp-org:service:ContentDirectory:1")]
    public interface IContentDirectory
    {
        [OperationContract(Action = "urn:schemas-upnp-org:service:ContentDirectory:1#Browse")]
        //void Browse(string ObjectID, string BrowseFlag, string Filter, ulong StartingIndex, ulong RequestedCount, string SortCriteria, out string Result, out ulong NumberReturned, out ulong TotalMatches, out ulong UpdateID);
        BrowseResponse Browse(BrowseRequest request);
    }
    public class Service : IContentDirectory
    {
        //public void Browse(string ObjectID, string BrowseFlag, string Filter, ulong StartingIndex, ulong RequestedCount, string SortCriteria, out string Result, out ulong NumberReturned, out ulong TotalMatches, out ulong UpdateID)
        //{
        //    Result = null;
        //    NumberReturned = 0;
        //    TotalMatches = 0;
        //    UpdateID = 0;
        //}
        public BrowseResponse Browse(BrowseRequest request)
        {
            return new BrowseResponse { NumberReturned = 0, Result = null, TotalMatches = 0, UpdateID = 0 };
        }
    }
    static Binding GetBinding()
    {
        return new CustomBinding(
            new TextMessageEncodingBindingElement(MessageVersion.Soap11WSAddressing10, Encoding.UTF8),
            new HttpTransportBindingElement());
    }
    public static void Test()
    {
        string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
        ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
        host.AddServiceEndpoint(typeof(IContentDirectory), GetBinding(), "");
        host.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true });
        host.Open();
        Console.WriteLine("Host opened");

        ChannelFactory<IContentDirectory> factory = new ChannelFactory<IContentDirectory>(GetBinding(), new EndpointAddress(baseAddress));
        IContentDirectory proxy = factory.CreateChannel();
        //string result;
        //ulong ul1, ul2, ul3;
        //proxy.Browse(null, null, null, 0, 0, null, out result, out ul1, out ul2, out ul3);
        proxy.Browse(new BrowseRequest { BrowseFlag = null, Filter = null, ObjectID = null, RequestedCount = 0, SortCriteria = null, StartingIndex = 0 });

        ((IClientChannel)proxy).Close();
        factory.Close();

        Console.Write("Press ENTER to close the host");
        Console.ReadLine();
        host.Close();
    }
}

Maintenant, la demande est envoyée par WCF est XML équivalent, mais les préfixes sont encore différents. Il Comme John Saunders a mentionné, il ne devrait pas question, donc il n'y a pas simple bouton dans WCF pour vous permettre de définir le préfixe pour les éléments écrits dans les messages WCF. Vous pouvez toutefois utiliser un encodeur personnalisé pour faire exactement cela. Je posté à ce sujet un certain temps à http://blogs.msdn.com/b/carlosfigueira/archive/2010/06/13/changing-prefixes-in-xml-responses.aspx - vous pouvez utiliser cet exemple pour créer une coutume encodeur qui fixera les préfixes à ce que vous attendez d'être.

Autres conseils

Pourquoi avez-vous besoin d'un préfixe spécifique? Utilisez-vous un logiciel qui dépend du préfixe?

Si tel est le cas, alors le logiciel est cassé. Les deux « xmlns » exemples que vous avez donnés sont identiques en ce qui concerne XML. Tout logiciel qui se soucie de la différence est mal cassé et a besoin d'apprendre XML.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top