locked
Error calling sharepoint web services from .net 3.5 WCF client... RRS feed

  • Question

  •  

     

    Code Snippet

                    using (OCUserProfileService.UserProfileServiceSoapClient service =
                        new TestAndDestroy.OCUserProfileService.UserProfileServiceSoapClient(GetWcfBinding())) {

                        service.ClientCredentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Impersonation;
                    
                        PropertyData[] properties = service.GetUserProfileByName("domain\\user.name");

                        foreach (PropertyData p in properties) {
                            Console.WriteLine(p.Name);
                            Console.WriteLine(p.Values);
                        }

     

     

     

    produces....
    The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://microsoft.com/webservices/SharePointPortalServer/UserProfileService:GetUserProfileByNameResponse. The InnerException message was 'Error in line 1 position 392. 'Element' 'IsPrivacyChanged' from namespace 'http://microsoft.com/webservices/SharePointPortalServer/UserProfileService' is not expected. Expecting element 'Name | Privacy'.'.  Please see InnerException for more details.

     

    I'm totally stumped, any ideas???

    Wednesday, July 16, 2008 8:52 PM

Answers

  • I rearranged the order of the fields and also saw the values for every propertydata were null. I think the issue is once you solve the ordering problem you encounter the next problem-- the WCF deserializer does not handle GUID values. The first PropertyData item returned from this service call is:

     

    <PropertyData><IsPrivacyChanged>false</IsPrivacyChanged><IsValueChanged>false</IsValueChanged><Name>UserProfile_GUID</Name><Privacy>Public</Privacy><Values><ValueData><Value xmlns:q1="http://microsoft.com/wsdl/types/" xsi:type="q1:guid">44bd0d07-4ac5-4faa-adaf-ef0214de27d7</Value></ValueData></Values></PropertyData>

     

    This blog entry has an in-depth discussion and proposed solution to the problem.

    http://blogs.msdn.com/b/silverlightws/archive/2010/05/17/workaround-for-accessing-some-asmx-services-from-silverlight-4.aspx

     

    I found the solution somewhat spartan, so here's how I implemented the behavior to get at the raw datastream:

     

    public

     

     

    class UserProfilesInspector : IClientMessageInspector

    {

     

     

    private string _accountName = "";

     

     

    public string AccountName

    {

     

     

    get { return _accountName; }

    }

     

     

    public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)

    {

     

     

    XDocument document = XDocument.Load(new System.IO.StringReader(reply.ToString()));

     

     

    // search for the elements you need here

    }

     

     

    public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel)

    {

     

     

    return null;

    }

    }

     

     

    public class UserProfilesBehavior : IEndpointBehavior

    {

     

     

    public UserProfilesInspector _inspector = new UserProfilesInspector();

     

     

    public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)

    { }

     

     

     

    public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)

    {

    clientRuntime.MessageInspectors.Add(_inspector);

    }

     

     

     

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)

    { }

     

     

     

    public void Validate(ServiceEndpoint endpoint)

    { }

    }

     

     

    public class UserProfiles : BaseConnector

    {

     

     

    private UserProfilesBehavior _behavior = new UserProfilesBehavior();

     

     

    public UserProfiles(Utilities.IActivityReporter activityReporter, Uri uri)

    :

     

    base(activityReporter, uri)

    {

    }

     

     

    public bool GetUserProfile(string accountName)

    {

     

     

    WSSUserProfiles.UserProfileServiceSoapClient up = new WSSUserProfiles.UserProfileServiceSoapClient();

    up.GetUserProfileByNameCompleted +=

     

    new EventHandler<WSSUserProfiles.GetUserProfileByNameCompletedEventArgs>(callback_GetUserProfileByNameCompleted);

    up.ChannelFactory.Endpoint.Behaviors.Add(_behavior);

     

     

    try

    {

    up.GetUserProfileByNameAsync(accountName, getUserProfileAsyncID());

    }

     

     

    catch (System.Exception sysex)

    {

     

    }

     

     

    return mSuccess;

    }

     

     

    private void callback_GetUserProfileByNameCompleted(object sender, WSSUserProfiles.GetUserProfileByNameCompletedEventArgs e)

    {

     

     

    // bypass the argument because silverlight 4 can't deserialize the xml from SharePoint for this call correctly

     

     

    string accountName = _behavior._inspector.AccountName);

    }

     

    Saturday, August 7, 2010 5:46 PM
  • I realise the last post on this was a couple of months ago but as it's a long running thread thought I would post my solution in case anyone still needs it.

    The order of the attributes needs to be:

    1. IsPrivacyChanged
    2. IsValueChanged
    3. Values
    4. Name
    5. Privacy

    I changed the order of the DataMemberAttributes in my reference.cs file and ensured the Order attributes matched the order:

     [System.Runtime.Serialization.DataMemberAttribute(IsRequired = true, Order = 1)]
        public bool IsPrivacyChanged
        {
          get
          {
            return this.IsPrivacyChangedField;
          }
          set
          {
            if ((this.IsPrivacyChangedField.Equals(value) != true))
            {
              this.IsPrivacyChangedField = value;
              this.RaisePropertyChanged("IsPrivacyChanged");
            }
          }
        }
    
        [System.Runtime.Serialization.DataMemberAttribute(IsRequired = true, Order = 2)]
        public bool IsValueChanged
        {
          get
          {
            return this.IsValueChangedField;
          }
          set
          {
            if ((this.IsValueChangedField.Equals(value) != true))
            {
              this.IsValueChangedField = value;
              this.RaisePropertyChanged("IsValueChanged");
            }
          }
        }
    
        [System.Runtime.Serialization.DataMemberAttribute(EmitDefaultValue = false, Order = 3)]
        public SharePointProfileViewer.UserProfileServiceReference.ValueData[] Values
        {
          get
          {
            return this.ValuesField;
          }
          set
          {
            if ((object.ReferenceEquals(this.ValuesField, value) != true))
            {
              this.ValuesField = value;
              this.RaisePropertyChanged("Values");
            }
          }
        }
    
        [System.Runtime.Serialization.DataMemberAttribute(EmitDefaultValue = false, Order = 4)]
        public string Name {
          get {
            return this.NameField;
          }
          set {
            if ((object.ReferenceEquals(this.NameField, value) != true)) {
              this.NameField = value;
              this.RaisePropertyChanged("Name");
            }
          }
        }
    
        [System.Runtime.Serialization.DataMemberAttribute(IsRequired = true, Order = 5)]
        public SharePointProfileViewer.UserProfileServiceReference.Privacy Privacy {
          get {
            return this.PrivacyField;
          }
          set {
            if ((this.PrivacyField.Equals(value) != true)) {
              this.PrivacyField = value;
              this.RaisePropertyChanged("Privacy");
            }
          }
        }

    This works for me!

    Thanks,

    Ben

    Monday, June 28, 2010 1:20 PM

All replies

  • i should mention that the same code in .net 2.0 works fine....

     

    Wednesday, July 16, 2008 8:53 PM
  • The good news is I can confirm this behavior.  The bad news is I'm also looking for a fix.  =(

    Friday, July 18, 2008 4:34 PM
  • I was able to reproduce as well.  The WSDL doesn't match the shape of the XML that is being returned from SharePoint.  The short-term fix is to change the generated proxy code to match the shape of what SharePoint is actually returning (versus what is exposed in its WSDL).  The actual shape of the message is:

     

    Code Snippet

    <s:complexType name="PropertyData">

    <s:sequence>

    <s:element minOccurs="1" maxOccurs="1" name="IsPrivacyChanged" type="s:boolean" />

    <s:element minOccurs="1" maxOccurs="1" name="IsValueChanged" type="s:boolean" />

    <s:element minOccurs="0" maxOccurs="1" name="Name" type="s:string" />

    <s:element minOccurs="1" maxOccurs="1" name="Privacy" type="s0:Privacy" />

    <s:element minOccurs="0" maxOccurs="1" name="Values" type="s0:ArrayOfValueData" />

    </< FONT></s:sequence>

    </< FONT></s:complexType>

     

     

     

    Notice that the IsPrivacyChanged and IsValueChanged elements need to appear first in the sequence.  For instance, you can change the generated WCF proxy type for the PropertyData class to look like the following:

     

    Code Snippet

    [System.Diagnostics.DebuggerStepThroughAttribute()]

    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "3.0.0.0")]

    [System.Runtime.Serialization.DataContractAttribute(Name="PropertyData", Namespace="http://microsoft.com/webservices/SharePointPortalServer/UserProfileService")]

    public partial class PropertyData : object, System.Runtime.Serialization.IExtensibleDataObject

    {

    private System.Runtime.Serialization.ExtensionDataObject extensionDataField;

    private bool IsPrivacyChangedField;

    private bool IsValueChangedField;

    private string NameField;

    private microsoft.com.webservices.SharePointPortalServer.UserProfileService.Privacy PrivacyField;

    private microsoft.com.webservices.SharePointPortalServer.UserProfileService.ValueData[] ValuesField;

    public System.Runtime.Serialization.ExtensionDataObject ExtensionData

    {

    get

    {

    return this.extensionDataField;

    }

    set

    {

    this.extensionDataField = value;

    }

    }

    [System.Runtime.Serialization.DataMemberAttribute(IsRequired=true)]

    public bool IsPrivacyChanged

    {

    get

    {

    return this.IsPrivacyChangedField;

    }

    set

    {

    this.IsPrivacyChangedField = value;

    }

    }

    [System.Runtime.Serialization.DataMemberAttribute(IsRequired=true)]

    public bool IsValueChanged

    {

    get

    {

    return this.IsValueChangedField;

    }

    set

    {

    this.IsValueChangedField = value;

    }

    }

    [System.Runtime.Serialization.DataMemberAttribute(EmitDefaultValue=false)]

    public string Name

    {

    get

    {

    return this.NameField;

    }

    set

    {

    this.NameField = value;

    }

    }

    [System.Runtime.Serialization.DataMemberAttribute(IsRequired=true)]

    public microsoft.com.webservices.SharePointPortalServer.UserProfileService.Privacy Privacy

    {

    get

    {

    return this.PrivacyField;

    }

    set

    {

    this.PrivacyField = value;

    }

    }

    [System.Runtime.Serialization.DataMemberAttribute(EmitDefaultValue=false)]

    public microsoft.com.webservices.SharePointPortalServer.UserProfileService.ValueData[] Values

    {

    get

    {

    return this.ValuesField;

    }

    set

    {

    this.ValuesField = value;

    }

    }

    }

     

     

     

     

    Monday, July 21, 2008 8:01 PM
  • I was able to reproduce as well. 


    Hi kirke!

    I have replace my PropertyData class, by your code, but it not help me.

    Now I have other similar error:
    "Error in line 1 position 11015. 'Element' 'Privacy' from namespace 'http://microsoft.com/webservices/SharePointPortalServer/UserProfileService' is not expected. Expecting element 'Name | Group | Email | Title | Url | IsInWorkGroup'." 
    • Edited by Mike Walsh FIN Friday, March 19, 2010 7:07 PM full quote uses too much space - don't use it
    Wednesday, June 3, 2009 2:40 PM
  • Unfortunately, I was never successful at calling SharePoint web services by adding a service reference. You can add a regular .net 2.0 service reference by clicking on the "Advanced" button when adding a service reference and then clicking on "Add Web Reference"

    http://social.msdn.microsoft.com/Forums/en-US/sharepointdevelopment/thread/c22f1633-7d68-4dde-b935-37e5e2fe3162/

     


    certdev.com
    Saturday, July 4, 2009 7:06 PM
  • You need to add the SharePoint Service as normal ASMX service reference i.e; Web Reference from the Add Service Reference wizard and it should be always basicHttpBinding, otherwise it wont work.
    Regards,
    Chakkaradeep

    Twitter: http://twitter.com/chakkaradeep
    Blog: http://www.chakkaradeep.com
    Saturday, July 4, 2009 11:34 PM
  • Thanks for the response Steve. That option is not available in my Advanced dialog. Must have something to do with this being a Silverlight project.
    Matthew McDermott, MVP MOSS
    Sunday, July 5, 2009 12:50 PM
  • Ok Silverlight is different. Chakkaradeep was pointing the correct way. When you add a service reference just point to the ASMX url, like http://localhost/sitename/_vti_bin/lists.asmx and then open up your ServiceReferences.ClientConfig file in your project and make sure it is using basicHttpBinding like below

    <configuration>
        <system.serviceModel>
            <bindings>
                <basicHttpBinding>
                    <binding name="ListsSoap" maxBufferSize="2147483647"
                        maxReceivedMessageSize="2147483647">
                        <security mode="None" />
                    </binding>
                </basicHttpBinding>
            </bindings>
            <client>
                <endpoint address="http://localhost/_vti_bin/lists.asmx"
                    binding="basicHttpBinding" bindingConfiguration="ListsSoap"
                    contract="ListsClient.ListsSoap" name="ListsSoap" />
            </client>
        </system.serviceModel>
    </configuration>
    Then you can create the web service proxy like so and call the methods on it asynchronously:

    ListsSoap ls = new ListsSoap("ListsSoap", "http://localhost/sitename/_vti_bin/lists.asmx);

    certdev.com
    Sunday, July 5, 2009 6:57 PM
  • Thanks guys. The issue appears t be with the UserProfileService. In your examples you are using Lists.asmx. I am calling UserProfileService.asmx. It appears that the XML result is malformed. It works in 2.0 applications but not 3.5 applications.

    I cannot mark your advice as an answer because it still does not work for the scenario that started the thread (though your advice may help others using the Lists.asmx or other SharePoint web service).

    I'll write my own WCF compliant service and use that.

    Thanks!

    Matthew
    Matthew McDermott, MVP MOSS
    Tuesday, July 7, 2009 12:41 PM
  • I was able to solve this issue and continue using .Net 3.5 by changing this in Reference.cs under the service reference in the UserProfileService.PropertyData class....

    [System.Runtime.Serialization.DataMemberAttribute(IsRequired = true, Order = 3)]
    
    public bool IsPrivacyChanged
    
    {
    
      get
    
      {
    
        return this.IsPrivacyChangedField;
    
      }
    
      set
    
      {
    
        if ((this.IsPrivacyChangedField.Equals(value) != true))
    
        {
    
          this.IsPrivacyChangedField = value;
    
          this.RaisePropertyChanged("IsPrivacyChanged");
    
        }
    
      }
    
    }
    
    
    
    [System.Runtime.Serialization.DataMemberAttribute(IsRequired = true, Order = 4)]
    
    public bool IsValueChanged
    
    {
    
      get
    
      {
    
        return this.IsValueChangedField;
    
      }
    
      set
    
      {
    
        if ((this.IsValueChangedField.Equals(value) != true))
    
        {
    
          this.IsValueChangedField = value;
    
          this.RaisePropertyChanged("IsValueChanged");
    
        }
    
      }
    
    }
    
    

     

    To this....

    [System.Runtime.Serialization.DataMemberAttribute(IsRequired = true)]
    
    public bool IsPrivacyChanged
    
    {
    
      get
    
      {
    
        return this.IsPrivacyChangedField;
    
      }
    
      set
    
      {
    
        if ((this.IsPrivacyChangedField.Equals(value) != true))
    
        {
    
          this.IsPrivacyChangedField = value;
    
          this.RaisePropertyChanged("IsPrivacyChanged");
    
        }
    
      }
    
    }
    
    
    
    [System.Runtime.Serialization.DataMemberAttribute(IsRequired = true)]
    
    public bool IsValueChanged
    
    {
    
      get
    
      {
    
        return this.IsValueChangedField;
    
      }
    
      set
    
      {
    
        if ((this.IsValueChangedField.Equals(value) != true))
    
        {
    
          this.IsValueChangedField = value;
    
          this.RaisePropertyChanged("IsValueChanged");
    
        }
    
      }
    
    }
    
    

    The trick is to simply remove the Order=# parameter from the attribute, also resequencing the schema according to kirke didn't hurt...

    [System.Runtime.Serialization.DataMemberAttribute(IsRequired = true, Order=#)]
    
    


    "There's a way to do it better - find it." - Thomas Edison

    P.S. Visual Studio Team System 2008 Developer


    • Proposed as answer by Gio Palacino Friday, March 19, 2010 5:25 PM
    • Unproposed as answer by Mike Walsh FIN Friday, March 19, 2010 7:07 PM
    • Edited by Mike Walsh FIN Saturday, March 19, 2011 7:15 AM P.S. taken from later post
    Friday, March 19, 2010 5:05 PM
  • Steve, this is not the answer. You are referencing the LISTS.asmx. This post is specifcally about UserProfileService.asmx.

    Matthew


    Matthew McDermott, MVP MOSS
    Wednesday, March 24, 2010 6:56 PM
  • Derik, I am curious what version of SharePoint Server and Visual Studio you are using. I ask because, though it appeared this was a solution, it is not for me. My Reference.cs is written like this:

    [System.Runtime.Serialization.DataMemberAttribute(IsRequired=true)]
            public bool IsValueChanged {
                get {
                    return this.IsValueChangedField;
                }
                set {
                    if ((this.IsValueChangedField.Equals(value) != true)) {
                        this.IsValueChangedField = value;
                        this.RaisePropertyChanged("IsValueChanged");
                    }
                }
            }

     

    Also, thank you for chipping in, this has been a sore spot for several months. The folks who are jumping in about LISTS.asmx dilute the conversation.

    Cheers, Matt

     

     


    Matthew McDermott, MVP MOSS
    • Edited by Mike Walsh FIN Thursday, March 25, 2010 4:31 AM references to 2010 removed. Save them for the 2010 forums please
    Wednesday, March 24, 2010 7:01 PM
  • The fundamental issue it the GetUserProfileByName method. Or any method returning PropertyData.

    I'll test Derek's solution on 2007.

     

    Matthew

     


    Matthew McDermott, MVP MOSS
    • Edited by Mike Walsh FIN Saturday, March 19, 2011 7:12 AM Tidied when cutting chat from long thread
    Thursday, March 25, 2010 12:40 PM
  • Still not working in 2007. Looking closely at the PropertyData signature mine is different from the one in Kirke's above. This is VS2008 and MOSS 2007 on a fresh project.

        [System.Diagnostics.DebuggerStepThroughAttribute()]
        [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "3.0.0.0")]
        [System.Runtime.Serialization.DataContractAttribute(Name="PropertyData", Namespace="http://microsoft.com/webservices/SharePointPortalServer/UserProfileService")]
        public partial class PropertyData : object, System.ComponentModel.INotifyPropertyChanged {
            
            private string NameField;
            
            private UPIssue.UPService.Privacy PrivacyField;
            
            private System.Collections.ObjectModel.ObservableCollection<UPIssue.UPService.ValueData> ValuesField;
            
            private bool IsPrivacyChangedField;
            
            private bool IsValueChangedField;
    
     I have no idea what is going on...

    Matthew McDermott, MVP MOSS
    Thursday, March 25, 2010 5:29 PM
  • @Matthew, Are you adding the reference as a WCF reference or as a Web Service reference? In SteveCl's original post, he's using a WCF reference, which is what I am using as well. Also, the attributes I mentioned "Order=#" are over the properties in that generated class and not the fields, if that helps any.
    "There's a way to do it better - find it." - Thomas Edison
    • Edited by Gio Palacino Wednesday, March 31, 2010 2:32 PM Typo
    Wednesday, March 31, 2010 2:32 PM
  • I realise the last post on this was a couple of months ago but as it's a long running thread thought I would post my solution in case anyone still needs it.

    The order of the attributes needs to be:

    1. IsPrivacyChanged
    2. IsValueChanged
    3. Values
    4. Name
    5. Privacy

    I changed the order of the DataMemberAttributes in my reference.cs file and ensured the Order attributes matched the order:

     [System.Runtime.Serialization.DataMemberAttribute(IsRequired = true, Order = 1)]
        public bool IsPrivacyChanged
        {
          get
          {
            return this.IsPrivacyChangedField;
          }
          set
          {
            if ((this.IsPrivacyChangedField.Equals(value) != true))
            {
              this.IsPrivacyChangedField = value;
              this.RaisePropertyChanged("IsPrivacyChanged");
            }
          }
        }
    
        [System.Runtime.Serialization.DataMemberAttribute(IsRequired = true, Order = 2)]
        public bool IsValueChanged
        {
          get
          {
            return this.IsValueChangedField;
          }
          set
          {
            if ((this.IsValueChangedField.Equals(value) != true))
            {
              this.IsValueChangedField = value;
              this.RaisePropertyChanged("IsValueChanged");
            }
          }
        }
    
        [System.Runtime.Serialization.DataMemberAttribute(EmitDefaultValue = false, Order = 3)]
        public SharePointProfileViewer.UserProfileServiceReference.ValueData[] Values
        {
          get
          {
            return this.ValuesField;
          }
          set
          {
            if ((object.ReferenceEquals(this.ValuesField, value) != true))
            {
              this.ValuesField = value;
              this.RaisePropertyChanged("Values");
            }
          }
        }
    
        [System.Runtime.Serialization.DataMemberAttribute(EmitDefaultValue = false, Order = 4)]
        public string Name {
          get {
            return this.NameField;
          }
          set {
            if ((object.ReferenceEquals(this.NameField, value) != true)) {
              this.NameField = value;
              this.RaisePropertyChanged("Name");
            }
          }
        }
    
        [System.Runtime.Serialization.DataMemberAttribute(IsRequired = true, Order = 5)]
        public SharePointProfileViewer.UserProfileServiceReference.Privacy Privacy {
          get {
            return this.PrivacyField;
          }
          set {
            if ((this.PrivacyField.Equals(value) != true)) {
              this.PrivacyField = value;
              this.RaisePropertyChanged("Privacy");
            }
          }
        }

    This works for me!

    Thanks,

    Ben

    Monday, June 28, 2010 1:20 PM
  • Thanks Ben

    It's working, but somehow the "Values" is always null.

    Help solve the problem.
    My code:
     [System.Diagnostics.DebuggerStepThroughAttribute()]
     [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
     [System.Runtime.Serialization.DataContractAttribute(Name="PropertyData", Namespace="http://microsoft.com/webservices/SharePointPortalServer/UserProfileService")]
     public partial class PropertyData : object, System.ComponentModel.INotifyPropertyChanged {
    
      private bool IsPrivacyChangedField;
    
      private bool IsValueChangedField;
    
      private System.Collections.ObjectModel.ObservableCollection<Test.Tree.UserProfileService.ValueData> ValuesField;
      
      private string NameField;
      
      private Test.Tree.UserProfileService.Privacy PrivacyField;    
    
      [System.Runtime.Serialization.DataMemberAttribute(IsRequired = true, Order = 1)]
      public bool IsPrivacyChanged
      {
       get
       {
        return this.IsPrivacyChangedField;
       }
       set
       {
        if ((this.IsPrivacyChangedField.Equals(value) != true))
        {
         this.IsPrivacyChangedField = value;
         this.RaisePropertyChanged("IsPrivacyChanged");
        }
       }
      }
    
      [System.Runtime.Serialization.DataMemberAttribute(IsRequired = true, Order = 2)]
      public bool IsValueChanged
      {
       get
       {
        return this.IsValueChangedField;
       }
       set
       {
        if ((this.IsValueChangedField.Equals(value) != true))
        {
         this.IsValueChangedField = value;
         this.RaisePropertyChanged("IsValueChanged");
        }
       }
      }
    
      [System.Runtime.Serialization.DataMemberAttribute(EmitDefaultValue = false, Order = 3)]
      public System.Collections.ObjectModel.ObservableCollection<Test.Tree.UserProfileService.ValueData> Values
      {
       get
       {
        return this.ValuesField;
       }
       set
       {
        if ((object.ReferenceEquals(this.ValuesField, value) != true))
        {
         this.ValuesField = value;
         this.RaisePropertyChanged("Values");
        }
       }
      }
      
      [System.Runtime.Serialization.DataMemberAttribute(EmitDefaultValue=false, Order=4)]
      public string Name {
       get {
        return this.NameField;
       }
       set {
        if ((object.ReferenceEquals(this.NameField, value) != true)) {
         this.NameField = value;
         this.RaisePropertyChanged("Name");
        }
       }
      }
      
      [System.Runtime.Serialization.DataMemberAttribute(IsRequired=true, Order=5)]
      public Test.Tree.UserProfileService.Privacy Privacy {
       get {
        return this.PrivacyField;
       }
       set {
        if ((this.PrivacyField.Equals(value) != true)) {
         this.PrivacyField = value;
         this.RaisePropertyChanged("Privacy");
        }
       }
      }
      
      public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
      
      protected void RaisePropertyChanged(string propertyName) {
       System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
       if ((propertyChanged != null)) {
        propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
       }
      }
     }
     
    

    vkv
    Monday, July 26, 2010 7:51 AM
  • I rearranged the order of the fields and also saw the values for every propertydata were null. I think the issue is once you solve the ordering problem you encounter the next problem-- the WCF deserializer does not handle GUID values. The first PropertyData item returned from this service call is:

     

    <PropertyData><IsPrivacyChanged>false</IsPrivacyChanged><IsValueChanged>false</IsValueChanged><Name>UserProfile_GUID</Name><Privacy>Public</Privacy><Values><ValueData><Value xmlns:q1="http://microsoft.com/wsdl/types/" xsi:type="q1:guid">44bd0d07-4ac5-4faa-adaf-ef0214de27d7</Value></ValueData></Values></PropertyData>

     

    This blog entry has an in-depth discussion and proposed solution to the problem.

    http://blogs.msdn.com/b/silverlightws/archive/2010/05/17/workaround-for-accessing-some-asmx-services-from-silverlight-4.aspx

     

    I found the solution somewhat spartan, so here's how I implemented the behavior to get at the raw datastream:

     

    public

     

     

    class UserProfilesInspector : IClientMessageInspector

    {

     

     

    private string _accountName = "";

     

     

    public string AccountName

    {

     

     

    get { return _accountName; }

    }

     

     

    public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)

    {

     

     

    XDocument document = XDocument.Load(new System.IO.StringReader(reply.ToString()));

     

     

    // search for the elements you need here

    }

     

     

    public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel)

    {

     

     

    return null;

    }

    }

     

     

    public class UserProfilesBehavior : IEndpointBehavior

    {

     

     

    public UserProfilesInspector _inspector = new UserProfilesInspector();

     

     

    public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)

    { }

     

     

     

    public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)

    {

    clientRuntime.MessageInspectors.Add(_inspector);

    }

     

     

     

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)

    { }

     

     

     

    public void Validate(ServiceEndpoint endpoint)

    { }

    }

     

     

    public class UserProfiles : BaseConnector

    {

     

     

    private UserProfilesBehavior _behavior = new UserProfilesBehavior();

     

     

    public UserProfiles(Utilities.IActivityReporter activityReporter, Uri uri)

    :

     

    base(activityReporter, uri)

    {

    }

     

     

    public bool GetUserProfile(string accountName)

    {

     

     

    WSSUserProfiles.UserProfileServiceSoapClient up = new WSSUserProfiles.UserProfileServiceSoapClient();

    up.GetUserProfileByNameCompleted +=

     

    new EventHandler<WSSUserProfiles.GetUserProfileByNameCompletedEventArgs>(callback_GetUserProfileByNameCompleted);

    up.ChannelFactory.Endpoint.Behaviors.Add(_behavior);

     

     

    try

    {

    up.GetUserProfileByNameAsync(accountName, getUserProfileAsyncID());

    }

     

     

    catch (System.Exception sysex)

    {

     

    }

     

     

    return mSuccess;

    }

     

     

    private void callback_GetUserProfileByNameCompleted(object sender, WSSUserProfiles.GetUserProfileByNameCompletedEventArgs e)

    {

     

     

    // bypass the argument because silverlight 4 can't deserialize the xml from SharePoint for this call correctly

     

     

    string accountName = _behavior._inspector.AccountName);

    }

     

    Saturday, August 7, 2010 5:46 PM
  • Thanks John for the article!

    So I checked the order of the returned items, I have this:

    1. IsPrivacyChanged
    2. IsValueChanged
    3. Name
    4. Privacy
    5. Values

    And everything worked! :)

    Thanks!!!


    vkv
    Friday, September 3, 2010 9:35 AM
  • All,

    At long last we have a solution that works for Silverlight 3 and Windows Phone: http://www.ableblue.com/blog/archive/2011/03/18/silverlight-and-sharepoint-user-profile-service-guids.aspx

    The solution for Silverlight 4 is here: http://blogs.msdn.com/b/silverlightws/archive/2010/05/26/workaround-for-accessing-some-asmx-services-from-silverlight-4.aspx

    Amazing this thread has been around since 2008!

    Cheers,

    Matthew


    Matthew McDermott, MVP SharePoint
    Friday, March 18, 2011 8:42 PM