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

BeforeProperties and AfterProperties of SPItemEventReceiver

BeforeProperties and AfterProperties: SPItemEventReceiver

There are two type of SharePoint events: Asynchronous (After) and Synchronous (Along) events.Synchronous events, e.g. are: ItemAdding, FieldUpdating, FeatureDeactivating etc… (like all those events that are having “-ing” as suffix).Asynchronous events, e.g. are: ItemAdded, FieldUpdated, FeatureActivated etc… (like all those events that are having “-ed” as suffix).

As far as AfterProperties and BeforeProperties are concerned for any event, they can help you to extract After and Before change in state about the object in context. This case is true and valid for any document library in context. For example, if you want to prevent any change in particular column of Document library your code must be:

public override void  ItemUpdating(SPItemEventProperties 
                                             properties)
{
     if (properties.BeforeProperties["column"] != 
                              properties.AfterProperties["column"])
    {
        properties.Cancel = true;
        properties.ErrorMessage = "This column cannot be changed";
    }
}

But such examples are only valid for Document Library in context, as per the Microsoft; as it is written inSDK that “For documents, Before and After properties are guaranteed for post events, such as ItemUpdated, but Before properties are not available for post events on list items”. So, statement written like these form the basis of analysis, on testing various events during Addition, Deletion and Update  of both SharePoint lists and SharePoint library, here is the conclusion that is actually drawn for any List:

List BeforeProperties AfterProperties properties.ListItem
ItemAdding No value New value Null
ItemAdded No value New value New value
ItemUpdating No value Changed value Original value
ItemUpdated No value Changed value Changed value
ItemDeleting No value No value Original value
ItemDeleted No value No value Null
No value means that column value in the hash table was not available.
New value means that the correct value for the column was available.
Changed value means that the correct updated value was available.
Original value means that the correct original value was available.
Here is the results on any document library:
Library BeforeProperties AfterProperties properties.ListItem
ItemAdding No value No value Null
ItemAdded No value No value New value
ItemUpdating Original value Changed value Original value
ItemUpdated Original value Changed value Changed value
ItemDeleting No value No value Original value
ItemDeleted No value No value Null
Properties.ListItem refers the the current value for the list item at that point in the event.  Null means that the item is not available.
Some noteworthy points are:
  • Not surprisingly, we get null values for for ItemAdding (before item is added) and ItemDeleted (after item is deleted).
  • As correctly documented in the SDK, item events for lists do not expose BeforeProperties.
  • ItemAdding and ItemAdded correctly report the value in the AfterProperties for an list item, but not a library item.  This is curious.
  • We have no visibility on the previous states during the ItemDeleted event.  Once it’s deleted, it’s clearly gone.

So, if we go back to our original problem listed above.  How can we prevent a user from changing a certain column for an item in a list event?  From the list table, you can see if we hook into the ItemUpdating event, we can compare the current item’s value (properties.ListItem) to the AfterProperties value.  The code would look like this:

if (properties.ListItem["column"] != 
                  properties.AfterProperties["column"])
{
    properties.Cancel = true;
    properties.ErrorMessage = "This column cannot be changed";
}

Hope this analysis provide you quite a clear picture about 
After/BeforeProperties on any Document Library and List.


Leave a comment

Creating Search Service Application using PowerShell In SharePoint

It might be necessary at some point to use PowerShell to provision search service applications. Below is the script which can be used for creating a Search Service Application With comments

Below is the Power Shell Script which I used for the creation Search Service Application

$searchapp = Get-SPEnterpriseSearchServiceApplication -Identity $SearchServiceApplicationName -ErrorAction silentlycontinue
//Check if the SearchService Application Already exists
if($searchapp -eq $null)
{
//For the content Source after the creation of the search service application
$contentSourceURls = “URL1″,”URL2″,”URL3″,”URL4”;
// Name of Application pool
$ManagedMetaDataAppPool =”MySearchServiceApplicationPoolAccount”
$ManagedAccount = Get-SPManagedAccount | select -First 1
// 1. Creating a an application pool for your search service application and throwing the object into a variable called $ app:
$ApplicationPool = Get-SPServiceApplicationPool $ManagedMetaDataAppPool -ErrorAction SilentlyContinue
if ($ApplicationPool -eq $null) {
$ApplicationPool = New-SPServiceApplicationPool -Name $ManagedMetaDataAppPool -Account $ManagedAccount
}
// “2. Creating search Service.”
$searchapp = New-SPEnterpriseSearchServiceApplication -name $SearchServiceApplicationName -applicationpool $ApplicationPool
//Note: Add the -partitioned switch after -name if the search service application will be consumed in a hosted environment.
// “3. Creating Search Service proxy.”
$proxy = New-SPEnterpriseSearchServiceApplicationProxy -name $SearchServiceApplicationName -Uri $searchapp.uri.absoluteURI
$si = Get-SPEnterpriseSearchServiceInstance –local
// “4. Start Services search services for SSI”
Start-SpEnterpriseSearchServiceInstance -identity $si
Set-SPEnterpriseSearchAdministrationComponent –searchapplication $searchapp –searchserviceinstance $si
// “5.Create a new Crawl Topology.”
// By default, a search application created in PowerShell has a crawl topology but is missing the following:
// · crawl component
// · query component
// You cannot add a crawl\query component to the default crawl\query topology because it’s set as active and the property is read // only. The easiest way around this is creating a new crawl topology and new query topology. After creating both, they will be // set as inactive by default. This allows for both crawl components to be added to crawl topology and query component to be added // to newly created query topology. Finally, you can set this new crawl topology to active.
$ct = $searchapp | New-SPEnterpriseSearchCrawlTopology
$csid = $SearchApp.CrawlStores | select id
$CrawlStore = $SearchApp.CrawlStores.item($csid.id)
// “6.Create a new Crawl Component.”
New-SPEnterpriseSearchCrawlComponent -crawltopology $ct -crawldatabase $Crawlstore -searchserviceinstance $SearchServiceInstance
net stop sptimerv4
net start sptimerv4
$done = $false
do
{
$ct | Set-SPEnterpriseSearchCrawlTopology -Active -ErrorVariable $err
if ($ct.State -eq “Active”)
{
$done = $true
}
Start-Sleep -Seconds 10
Write-Host $ct.State
}
until ($done -eq $true)
// “7. Create a new Query Topology.”
$qt = $searchapp | new-spenterprisesearchquerytopology -partitions 1
$p1 = ($qt | get-spenterprisesearchindexpartition)
// “8. Create a Query Component.”
new-spenterprisesearchquerycomponent -indexpartition $p1 -querytopology $qt -searchserviceinstance $si
$PSID = $SearchApp.PropertyStores | Select id
$PropDB = $SearchApp.PropertyStores.Item($PSID.id)
$p1 | set-spenterprisesearchindexpartition -PropertyDatabase $PropDB
$done = $false
do
{
$qt | Set-SPEnterpriseSearchQueryTopology -Active -ErrorVariable $err -ErrorAction SilentlyContinue
if ($qt.State -eq “Active”)
{
$done = $true
}
Start-Sleep -Seconds 10
Write-Host $qt.State
}
until ($done -eq $true)
// “9. Adding the content source urls.”
$contentSource = New-SPEnterpriseSearchCrawlContentSource -Name “My ContentSource” -SearchApplication $searchapp -Type SharePoint -SharePointCrawlBehavior “CrawlSites”
foreach ($contentSourceURl in $contentSourceURls)
{
$contentSource.StartAddresses.Add($($Url.Trim(“/”)+$contentSourceURl))
}
}


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);


6 Comments

Adding Services to Default Application Proxy Group in SharePoint 2010 Using Powershell

$serviceAppProxy = Get-SPServiceApplicationProxy | where { $_.Name -eq “Name of the service” }
$proxygroup = Get-SPServiceApplicationProxyGroup | where { $_.FriendlyName -eq “[default]” }
Add-SPServiceApplicationProxyGroupMember -Identity $proxygroup -Member $serviceAppProxy