manoj´ssharepointblog

SharePoint Blog


Leave a comment

How To: Check if a user is part of a SharePoint group in web based InfoPath form

I know that there are so many articles about this topic, but many of them were too complicated for many people to understand and most of the available articles only work with Classic authentication and not claims.

I have a group called MYInfopathGroup in which I want to check if the current  user is part of that SharePoint group. Below are the fields to show you  how it look like.

fieldInfo

First we need to retrieve the Account Name of the current logged in User. We can retrieve this information by using userprofileservice.asmx, Below are the steps to create the data connection. I am going to write a detailed article about how to retrieve the Account Name.

  • Click on Data Connections under the Data tab and select Add
  • Create a new connection to receive data
  • Select the SOAP Web service option
  • For the location  of the web service type:http://MyServerURL/_vti_bin/UserProfileService.asmx
  • Select the GetUserProfileByName method and click Next
  • Use the default settings in the next screen and click Next again
  • Click Next
  • Use the default settings, click Finish and close the dialog window

Select the properties of the username field from the main source.

  • Now add rules to the form load of the infopath form.
  • We need to add 3 rules.
  • Remove the second double click to insert field and replace it with“ABCDEFGHIJKLMNOPQRSTUVWXYZ” (incl. the quotiation marks)
  • Remove the third double click to insert field and replace it with “abcdefghijklmnopqrstuvwxyz”(incl. the quotiation marks)
  • The function should now look as follows:
    translate(double click to insert field; “ABCDEFGHIJKLMNOPQRSTUVWXYZ”; “abcdefghijklmnopqrstuvwxyz”)
  • For the first parameter double click on double click to insert field
  • From the drop down select the GetUserProfileByName data source
  • Expand the dataFields group as shown in the screenshot and select Value

GetUserProfileByName

Select the filter data and the filter should look like this.

GetUserProfileByNameFilter

At this stage the form queries the current user’s account name and stores it in the username field on form open. The forms runs fine on the InfoPath client but when we use the same form in the browser we get Access denied.

To over come this issue you need to Convert the data connection to Udcx file. We can achieve this by just clicking on the Convert to Connection file button available on the Data Connections.

Go to the data connection library and open the file in notepad and uncomment the udc:Authentication tag in the generated data connection udcx file.

Below is the sample tag

<udc:Authentication>

<udc:SSO AppId=’InfoPathWebService’ CredentialType=’NTLM’ />

</udc:Authentication>

Next we will query the UserGroup web service to get us a list of users in a specific SharePoint group:

  The UserGroup web service contains a method “GetUserCollectionFromGroup” which we will use in our setup:
  • Click on Data Connections under the Data tab and select Add
  • Create a new connection to receive data
  • Select the SOAP Web service option
  • For the location  of the web service type:http://MyServerUrl/_vti_bin/UserGroup.asmx
  • Select the GetUserCollectionFromGroup method and click Next
  • In the next screen select Set Sample Value and provide InfoPath with the name of the group you want to query (e.g. if your user is in a SharePoint group “Test” put in “Test“)
  • Click Next
  • Provide InfoPath with the same group name in the next screen and click Next again
  • Click Next
  • Use the default settings, click Finish and close the dialog window

We need to save our form and then use the Export Source Files option under “Publish“ tab.

Export

Once that is done, close the form and navigate to the location where you exported your form to. Open the file named “GetUserCollectionFromGroup1.xsd“. This file defines the XML schema. Open the file in Notepad++ or Visual Studio

Right under this code within the file:

<s:import namespace=”http://www.w3.org/2001/XMLSchema”></s:import>

<s:complexType name="GetUserCollectionFromGroupType">
 <s:sequence>
  <s:element minOccurs="0" maxOccurs="1" name="Users">
   <s:complexType>
    <s:sequence>
     <s:element maxOccurs="unbounded" name="User" >
      <s:complexType>
       <s:attribute name="Notes" type="s:string"></s:attribute>
       <s:attribute name="Name" type="s:string"></s:attribute>
       <s:attribute name="IsSiteAdmin" type="s:string"></s:attribute>
       <s:attribute name="Sid" type="s:string"></s:attribute>
       <s:attribute name="ID" type="s:string"></s:attribute>
       <s:attribute name="LoginName" type="s:string"></s:attribute>
       <s:attribute name="Email" type="s:string"></s:attribute>
       <s:attribute name="IsDomainGroup" type="s:string"></s:attribute>
      </s:complexType>
     </s:element>
    </s:sequence>
    </s:complexType>
  </s:element>
 </s:sequence>
</s:complexType>

Now locate the following piece of code within your file:

and replace it with this:
<!--<s:element name="GetUserCollectionFromGroup">
  <s:complexType> 
    <s:sequence> 
      <s:element minOccurs="0" maxOccurs="1" name="groupName" type="s:string"></s:element>
    </s:sequence> 
  </s:complexType> 
</s:element>-->
<s:element name="GetUserCollectionFromGroup" type="tns:GetUserCollectionFromGroupType" />

Now save the file and open the manifest.xsf by right clicking it and select Design.

If you have a look at your GetUserCollectionFromGroup data source and its fields, you will notice that it has changed from this:

before

Will look like this

after

Now the last thing we need to do is setup the IsGroupMember field. We want it to return a 1 if the user is in the group and a 0 if the user is not in the group.

  • Right click the IsGroupMember field and select Properties:
    • In the property window select the formula button for the default value
    • Select Insert Function
    • Select the Count function
    • Remove doube click to insert field
    • Within the Count function click Insert Function and add the translate function
    • Remove the second double click to insert field and replace it with“ABCDEFGHIJKLMNOPQRSTUVWXYZ” (incl. the quotation marks)
    • Remove the third double click to insert field and replace it with“abcdefghijklmnopqrstuvwxyz” (incl. the quotation marks)
    • For the first parameter double click on double click to insert field
    • Select the GetUserCollectionFromGroup data source
    • Expand the dataFields group and select “LoginName”
    • Select Filter Data and add a new filter
    • Leave the first drop down as is (It should show “LoginName“)
    • Select “Select a field or group” in the third drop down
    • Select the “Main” data source
    • Select the “CurrentUserAccountName” field
    • Confirm all open windows by clicking on “OK

We are done. You can now use the “IsGroupMember” field to hide and show different sections and fields in your form based on if the user is a member of the configured SharePoint group.

One thing to be aware of though is, that whenever you change the “GetUserCollectionFromGroup” data source, you will need to go through the setup process again for this data source.

Advertisements


Leave a comment

This functionality is unavailable for field collections not associated with a list

For my scenario the above issue occurs when I try to add a field to the content type i.e. when i use ContentType.AddField.

I have solved the above issue by using SPFieldLink instead of SPField

Below is code for your reference

SPContentType cDocumen = newSPContentType(null,Web.ContentTypes,“MyDocument”);

Web.ContentTypes.Add(cDocumen);

Web.Fields.Add(“Autor”, SPFieldType.Text, false);

SPFieldLink SPFLautor = newSPFieldLink(miWeb.Fields[“Autor”]);ctDocumento.FieldLinks.Add(SPFLautor);

cDocumen.Update();


2 Comments

Ampersands Comparision Issue in a Taxonomy term

There are two types of ampersands that you need to be aware of when playing with SharePoint Taxonomy

Our favorite and most loved

& ASCII Number: 38

And the impostor

& ASCII Number: 65286

When you create a term it replaces the 38 ampersand with a 65286 ampersand.

This then becomes a problem if you want to do a comparison with your original source (spreadsheet, database, etc) as they are no longer the same.

As detailed in Nick’s article, you can use the TaxonomyItem.NormalizeName method to create a “Taxonomy” version of your string for comparison.

Below is the code I used in the SharePoint 2013 Client Component which is a little different from the server code.

string myString = “Current accounts & cards
using (var context = new ClientContext(“http://MyTestSite”))
{
var result = TaxonomyItem.NormalizeName(context, myString);
context.ExecuteQuery();

string normalisedString = result.Value;
}

In Server Object model it is TaxonomyItem.NormalizeName(myString);


Leave a comment

How to programmatically search for the Index Component in SharePoint 2013

At the company I work for, we are going to start working with synonyms in our Search results (we are still on SharePoint 2010). The synonyms will be maintained by our Content Editors team and therefore I decided to let them maintain the synonyms in the term store (Managed metadata service application), as it is done in SharePoint 2013. Every night a timer job will run to read the term store and to create the tsenu.xml file and to copy it to the \Microsoft Office Servers\14.0\Data\Office Server\ApplicationsGUID-query-0\config\tsenu.xml folder.

When our code goes in production, it goes through a DTAP process, meaning that our code needs to be deployed on dev, on test, on acceptance before it goes in production. So we have different SharePoint farms for the different environments. Although the SharePoint folders our always deployed to the same drive, the folder for the tsenu.xml can be different as one of the folders is the GUID of the Search Service Aplication. So I wanted that the timer job would figure out the correct folder using the Search topology.

SearchService s = new SearchService(“OSearch14”, SPFarm.Local);
if (s != null)
{
var srchApp = from SearchServiceApplication sapp in s.SearchApplications
where sapp.Name == “Enterprise Search Service Application”
select sapp;

SearchServiceApplication serviceApp = srchApp.FirstOrDefault();
if (serviceApp != null)
{
var queryComponent = serviceApp.QueryTopologies.ActiveTopology.QueryComponents.FirstOrDefault();
if (queryComponent != null)
{
string serverName = queryComponent.ServerName;
string directoryPath = queryComponent.IndexLocation;
string foldername = queryComponent.Name;

string configfoldername = directoryPath + “\\” + foldername + “\\Config”;
}
}
}


Leave a comment

How to Programmatically find Search Service Application in SharePoint 2013

We found a lot of posts that use the GetDefaultProxy method to get to the Search Service Application but in our case this piece of code always returned our first Search Service Application.

SPServiceContext serviceContext = SPServiceContext.GetContext(site);
SearchServiceApplicationProxy searchProxy =
serviceContext.GetDefaultProxy(typeof(SearchServiceApplicationProxy)) as SearchServiceApplicationProxy;
if (searchProxy != null)
{
SearchServiceApplicationInfo searchServiceAppInfo = searchProxy.GetSearchServiceApplicationInfo();
SearchServiceApplication searchServiceApp = SearchService.Service.SearchApplications.GetValue(
searchServiceAppInfo.SearchServiceApplicationId);
Schema searchSchema = new Schema(searchServiceApp);
}

Finally we came out with the following piece of code to get to the correct Search Service Application:

SPServiceContext serviceContext = SPServiceContext.GetContext(site);
SearchService searchService = new SearchService(“OSearch14”, SPFarm.Local);

var srchApp = from SearchServiceApplication sapp in searchService.SearchApplications
where sapp.Name == “Our other search service application”
select sapp;

SearchServiceApplication searchServiceApp = srchApp.First();
searchSchema = new Schema(searchApplication);This does not seemed to be the best way to get to a service application and after some time of research I found out that you can also write it like this, which seems a better way to me:

searchApplication = (SearchServiceApplication)SPFarm.Local.Services.
GetValue().
Applications.GetValue(“Our other search service application”);
It took us several hours to find this out, but I hope that these snippets can save someone a few hours in the future.