Guest Post on the Arvato Systems Cloud Blog

Guest Post on the Arvato Systems Cloud Blog

I’ve published an article on the Arvato Systems Cloud Blog (German) and Arvato Systems Blog (English).

Geld sparen mit serverloser Architektur

Ihr Unternehmen plant eine großangelegte Digitalkampagne zur Vermarktung eines neuen Produktes? Sie sind nicht sicher, ob die aktuelle Architekturlösung den Ansprüchen ihrer geplanten Kampagne gerecht werden kann? Bei einem Ausbau Ihrer Infrastruktur würden hohe Kosten auf Sie zukommen?

How a serverless architecture can help you scale easily and save costs during your next marketing campaign

Is scaling up your existing infrastructure very expensive? Are you not sure if your infrastructure can meet the demands of your next big marketing campaign? Get to know an alternative to scale up your current environment for a short period.

Often there is no need to set up an infrastructure like a web server, database server, and load balancers. Let us take a look at some cloud providers and how they can serve our content more cost efficient and deliver websites to the visitors with high performance.

Azure Meetup OWL

Am 13.7. wird das erste Treffen des Azure Meetups OWL stattfinden. Wir sind derzeit noch auf der Suche nach einem Ort und den Themen 🙂
Vermutlich wird es um Chatbots und Machine Learning gehen. Wir werden aber auch auf euer Feedback eingehen um Themen für die nächsten Treffen zu finden.

Wenn ihr dabei sein möchtet, meldet euch bitte über die Meetup Seite an.

Update:

Ort: Arvato Systems, An der Autobahn 100, Gütersloh, Tower I

Zeit: 19:00 – 21:00 Uhr

Es wird um eine namentliche Anmeldung gebeten, da die Besucher beim Pförtner angemeldet werden müssen. Bitte entweder über Meetup, oder sendet mir eine E-Mail.

Widgets instead of Add-Ins/Apps?

The concept of Add-Ins (formally knows as Apps) in SharePoint puts logic as HTML and CSS to another page. This page is then rendered as iFrame to another SharePoint page. This approach has advantages and disadvantages. You have to decide yourself.

A very promising way to put stuff (or WebParts) onto a SharePoint page is the Widget Wrangler.

More information can be found on https://dev.office.com/blogs/introducing-widget-wrangler.

Conceptually Widget Wrangler implementation is based on similar thinking as PnP App Script Part implementation, which was released few years back as part of the PnP patterns (or at the time it was call App Model Samples). Advantages of this model is that you do not have deal with iFrame implementations and functionalities can be fully responsive, where needed. Also implementation of the capabilities is much simpler when your JavaScript is directly embedded to the page rendering logic without additional complexity.

In demo section Bob is showing following topics

  • How to use Widget Wrangler with plan JavaScript?
  • How to use Widget Wrangler with jQuery?
  • How to use Widget Wrangler with KnockoutJS?
  • How to use Widget Wrangler with Angular?
  • How does Widget Wrangler handle multiple instances of same widget in the SharePoint Pages?

I like that. As soon as I’ve some spare time, I will take a close look.

Treffen der SharePoint UserGroup OWL

Liebe SharePoint UserGroup,

es ist so weit. Nach einigen Abstimmungsrunden möchten wir Sie nun am Dienstag, 01. September 2015 zu unserem nächsten Treffen der SharePoint UserGroup OWL herzlich nach Gütersloh einladen.

Die Agenda steht nun bereit und sieht folgende Vorträge vor:

Ab in die Cloud – Migrationserfahrungen (Referent: René Hézser, arvato Systems)

Vorstellung von Nintex für Office 365 (live) (Referent: Henning Eiben, Busitec)

Das Treffen findet wie beim letzten Mal auf dem Campus von arvato Systems im Raum Barcelona / Madrid im Tower I  statt und startet ab 18 Uhr. Um Ihnen einen reibungslosen Zutritt zum Firmengelände zu gewähren, bitten wir um Ihre namentliche Anmeldung auf Xing, damit wir Sie beim Pförtner vormerken und natürlich auch für Ihr leibliches Wohl sorgen können.

Die Teilnehmeranzahl ist begrenzt, melden Sie sich deshalb schon jetzt an. Damit wir wieder eine Vielzahl von SharePoint-Interessenten an einen Tisch bringen, leiten Sie den Termin doch bitte in Ihrem Netzwerk weiter!

Wir freuen uns wieder auf einen informativen Erfahrungsaustausch.

Fix “Access Denied” on Registry and Filesystem

Today I installed the May CU on a SharePoint 2013 farm hosted in Azure. After the Installation was done (with a PowerShell script that disables some services to speed up the process), there were Exceptions opening the User Profile Service (UPS) settings page.

So I investigated the logs and found many entries about “Access Denied”. Some directly pointed to the registry hive “HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office Server\15.0” with the message Requested registry access is not allowed. or Getting Error Message for Exception System.Security.SecurityException: Requested registry access is not allowed., others about access to directories Access to the path ‘C:\Program Files\Microsoft Office Servers\15.0\Data\Office Server\CanonicalResources\ProjectionModels\EN_EN.mdl’ is denied.

Well, the short answer to fix the problem is: You need to execute the SharePoint Configuration Wizard on each server of the farm after installing an update.

Need users in your dev environment?

Often, you’ll need some users with data like picture and manager in your new development environment. Since you usually recycle your dev AD, this doesn’t happen frequently. But if you have to set up a new domain, you’ll want testusers with data.

I don’t want to search again, because I found a great resource for creating users here: http://mrhodes.net/2011/10/25/adding-285-contoso-users-with-pictures-to-your-development-environment-active-directory/

Have fun with PowerShell

Create the default groups via PowerShell

If your site is missing the three default groups “Visitors”, “Members” and “Owners”, you can create them easily with PowerShell or the Object Model.

Add-PSSnapin Microsoft.SharePoint.PowerShell

$web = Get-SPWeb https://your.site.url
if ($web.AssociatedVisitorGroup -eq $null) {
    Write-Host 'The Visitor Group does not exist. It will be created...' -ForegroundColor DarkYellow
    $currentLogin = $web.CurrentUser.LoginName

    if ($web.CurrentUser.IsSiteAdmin -eq $false){
        Write-Host ('The user '+$currentLogin+' needs to be a SiteCollection administrator, to create the default groups.') -ForegroundColor Red
        return
    }

    $web.CreateDefaultAssociatedGroups($currentLogin, $currentLogin, [System.String].Empty)
    Write-Host 'The default Groups have been created.' -ForegroundColor Green
} else {
    Write-Host 'The Visitor Group already exists.' -ForegroundColor Green
}

 

Update to the SharePoint Solution Deployer

A new version is out. If brings some great new extensions (two of them are from me 🙂 )

v5.0.4.6440 (2015-04-04)

  • New: All extensions added: Blocked file extensions, content type hub, custom crawl connector, features, logging configuration, managed metadata, re-ghost, search schema, secure store, site structure, CSOM extensions for files and 2013 workflows
  • Updated: SharePointVersions.xml
  • Updated: Typos in comments fixed and some code clean-up
  • First release based on GitHub repository

Grab your version from http://spsd.codeplex.com

Speaker auf der ShareConf

Gute Nachrichten. Beide meine Sessions wurden angenommen. Ich werde also zwei Sessions auf der ShareConf halten.

Ab in die Cloud – Migrationserfahrungen

Wie migriere ich Dienste von einer On-Premise Installation in die Cloud. Wohin mit Mail, SharePoint Blogs, Team Foundation Server und Backups? Warum überhaupt in „die Cloud“ und was ist dabei zu beachten?

SharePoint-Performance aus der Sicht eines Entwicklers

Sie sind Entwickler, arbeiten mit SharePoint und möchten mehr über die Arbeitsweise von SharePoint wissen? Wie kann die Gesamtperformance verbessert werden? In der Session gehen wir auf die Themen Suche, Server OM, Clientscript, sowie Aggregation uvm ein.

Redirect browser to a sub directory with WordPress

My blog is running with WordPress in the sub directory blog of my domain. If you, as a visitor, forget to enter /blog, this little index.php file in my root directory will redirect your browser to the sub directory.

<?php
@include("sitefunctions.php");
 
/* Move page with 301 http status code*/
movePage(301,"http://www.hezser.de/blog");
?>

You’ll need a sitefunction.php file with this content as well. The status code can be adjusted to your needs.

<?php
function movePage($num,$url){
   static $http = array (
       100 => "HTTP/1.1 100 Continue",
       101 => "HTTP/1.1 101 Switching Protocols",
       200 => "HTTP/1.1 200 OK",
       201 => "HTTP/1.1 201 Created",
       202 => "HTTP/1.1 202 Accepted",
       203 => "HTTP/1.1 203 Non-Authoritative Information",
       204 => "HTTP/1.1 204 No Content",
       205 => "HTTP/1.1 205 Reset Content",
       206 => "HTTP/1.1 206 Partial Content",
       300 => "HTTP/1.1 300 Multiple Choices",
       301 => "HTTP/1.1 301 Moved Permanently",
       302 => "HTTP/1.1 302 Found",
       303 => "HTTP/1.1 303 See Other",
       304 => "HTTP/1.1 304 Not Modified",
       305 => "HTTP/1.1 305 Use Proxy",
       307 => "HTTP/1.1 307 Temporary Redirect",
       400 => "HTTP/1.1 400 Bad Request",
       401 => "HTTP/1.1 401 Unauthorized",
       402 => "HTTP/1.1 402 Payment Required",
       403 => "HTTP/1.1 403 Forbidden",
       404 => "HTTP/1.1 404 Not Found",
       405 => "HTTP/1.1 405 Method Not Allowed",
       406 => "HTTP/1.1 406 Not Acceptable",
       407 => "HTTP/1.1 407 Proxy Authentication Required",
       408 => "HTTP/1.1 408 Request Time-out",
       409 => "HTTP/1.1 409 Conflict",
       410 => "HTTP/1.1 410 Gone",
       411 => "HTTP/1.1 411 Length Required",
       412 => "HTTP/1.1 412 Precondition Failed",
       413 => "HTTP/1.1 413 Request Entity Too Large",
       414 => "HTTP/1.1 414 Request-URI Too Large",
       415 => "HTTP/1.1 415 Unsupported Media Type",
       416 => "HTTP/1.1 416 Requested range not satisfiable",
       417 => "HTTP/1.1 417 Expectation Failed",
       500 => "HTTP/1.1 500 Internal Server Error",
       501 => "HTTP/1.1 501 Not Implemented",
       502 => "HTTP/1.1 502 Bad Gateway",
       503 => "HTTP/1.1 503 Service Unavailable",
       504 => "HTTP/1.1 504 Gateway Time-out"
   );
   header($http[$num]);
   header ("Location: $url");
}
?>

Unfortunately I don’t remember where I got this idea from 🙁

The SharePoint Solution Deployer

Deploying Solutions can be a …. (fill in as you wish).

The SharePoint Solution Deployer offers a great opportunity to writing your own scripts. The existing functionality should match your needs to deploy SharePoint Solutions. If not, the “framework” can be extended with custom Extensions or simple PowerShell code.

I’ve written two Extensions, which let you enable and disable features upon deployments and reset files to their site definitions (aka ReGhost).

To be able to have different URLs for your dev-machine, staging and production farms, simply create additional XML-files and configure URLs there. The XML-file needs to be named with the hostname of the server, where you want start the deployment.

Example

The example shows two files within the Environment subfolder.

Default XML Configuration file (Default.xml)

<?xml version="1.0" encoding="utf-8" ?>
<SPSD Version="5.0.3.6439">
	<Configuration ID="Default">
		...
	</Configuration>

	<Environment ID="Default">

		<Variables ID="Default">
			<!-- Default values are for production. Change values in Hostname.xml file to your needs.-->
			<Variable Name="CentralAdministrationWebAppUrl">https://xxx:11111</Variable>
			<Variable Name="WebAppUrl">https://prod.sharepoint.local</Variable>
		</Variables>

		<PreRequisiteSolutions ID="Default">
			...
		</PreRequisiteSolutions>

		<Solutions ID="Default" Force="false" Overwrite="true">
			...
		</Solutions>
	</Environment>
</SPSD>

 Hostname.xml

The script will look if there is any XML file with the name “hostname.xml”

<?xml version="1.0" encoding="utf-8" ?>
<SPSD Version="5.0.3.6439">
	<Environment ID="Default">

		<Variables ID="Default">
			<!-- Default values are for production. Change values in Hostname.xml file to your needs.-->
			<Variable Name="CentralAdministrationWebAppUrl">https://xxx:22222</Variable>
			<Variable Name="WebAppUrl">https://dev.sharepoint.local</Variable>
		</Variables>
	</Environment>
</SPSD>

That’s it.

You can start the deployment with e.g. “Redeploy.bat” from the Rootfolder, no matter which farm you are on.

Use a XML-file for configuration in PowerShell scripts

Time for some PowerShell!

Almost every PowerShell script need some configuration parameters. With this post I want to show one way, there are others ;-), to parse a config file in XML format and use the values later.

The solution I’m going to show to you contains three files. A PowerShell script, a XML configuration file and a helper PowerShell file that contains a function to parse the config file.

PowerShell XML config files

The config file contains

<config>
	<hyperv dir="C:\Hyper-V\New_Server">
		<ram>2048</ram>
	</hyperv>
</config>

The helper function to parse the configuration file looks like this

# Parse Configuration file
function ParseConfig([string]$filename) {
	try {
		$file = Get-Item -Path $filename
		if ($file.Exists) {
			$root = "config"
			$cfg = [xml] ( Get-Content -Path $filename )
			return $cfg.config
		}
		else {
			Write-Host "The configuration file "$filename" does not exist" -ForegroundColor Red
		}
	}
	catch {
		Write-Host "Cannot load configuration file "$filename -ForegroundColor Red
	}
	return $null
}

And finally the main script, that will reference the helper function, call it and use the values.

# modify here
$cfgFile = "NewHyperVConfig.xml"
# stop modifying content below
# ----------------------------

# load functions from other files
. "$PSScriptRoot\helper\Configuration.ps1"

# load and parse config from xml file
$cfg = ParseConfig $PSScriptRoot"\"$cfgFile

# start doing something
Write-Host $cfg.hyperv.dir
Write-Host $cfg.hyperv.ram

Summary: Store configuration settings in a XML file and use the values in PowerShell script.

Getting the PageTitle

Getting the PageTitle of a page should be just a property away would you think. I would call Page.Title to get the title of the current page.

Unfortunately Page.Title contains “\r\n           ” and the title of the page is in a new line, like this:

<title>
	
	RH Test

</title>

The property will only return the first row, which is not very helpful 🙁

So what can we do? Since the title is set through a control within a ContentPlacehoder, my way was to get the control and take the value from it. And… it worked. An extension method will traverse all controls, to find the desired one.

public string GetPageTitle()
{
	var literal = Page.Header.FindControlsOfType<ContentPlaceHolder>().Single(p => p.ID == "PlaceHolderPageTitle").FindControlsOfType<EncodedLiteral>().FirstOrDefault();
	if (literal != null)
	{
		string pageTitle = literal.Text;
		return pageTitle;
	}
	return null;
}

// and an extension method (need to go to a static class!
public static IEnumerable<T> FindControlsOfType<T>(this Control control) where T : Control
{
	foreach (Control child in control.Controls)
	{
		if (child is T)
		{
			yield return (T)child;
		}
		else
		{
			foreach (T grandChild in child.FindControlsOfType<T>())
			{
				yield return grandChild;
			}
		}
	}
}

Page.Title, I got you 😉

Treffen der SharePoint Usergroup OWL am 9.12.14

Am 9.12. ist es wieder soweit. Derzeit sind zwei Vorträge gesetzt:

  • SharePoint Hosting – Ist die Cloud schon geeignet dafür? von Daniel Lindemann (ITaCS GmbH)
  • Das Spannungsfeld Development-Operation im Umfeld von SharePoint Hosting von Andre Tomasiewicz (arvato Systems)

Wir treffen uns um 18h. Die Adresse lautet:

An der Autobahn 200
33333 Gütersloh

https://www.google.de/maps/dir//51.8841959,8.4429219/@51.8834721,8.4421559,17z?hl=de

Da der Raum sich auf dem Firmengelände befindet, ist eine namentliche Voranmeldung erforderlich.

Updating the title within a SPItemEventReceiver with AfterProperties

Recently I had a problem setting the title field of a Page within the pages library. My requirement was to set the title with the value from the PageTitle field of the current item.

An ItemEventReceiver, which is executed synchronously to prevent save conflict exception or problems with published items, was supposed to do exactly that. But when I set the title property of the item via AfterProperties, the value did not get stored. I tried other fields, and they got written to the item just fine. After some trial-and-error and consulting the MSDN I found a solution.

The ItemEventReceiver needs to update the vti_title field instead. This field exists on a SPFile. And since a Page is a SPFile, you’ll need to modify that field instead.

public override void ItemAdding(SPItemEventProperties properties)
{
	base.ItemAdding(properties);
	UpdateTitleField(properties);
}

public override void ItemUpdating(SPItemEventProperties properties)
{
	base.ItemUpdating(properties);
	UpdateTitleField(properties);
}

/// <summary>
/// Set title from PageTitle
/// </summary>
/// <param name="properties"></param>
private void UpdateTitleField(SPItemEventProperties properties)
{
	var title = Convert.ToString(properties.AfterProperties["PageTitle"]);
	if (!string.IsNullOrEmpty(title) && properties.List.Fields.ContainsFieldWithStaticName("vti_title"))
		properties.AfterProperties["vti_title"] = title;
}

With this code, the title of my page was changed as supposed to.

.NET goes OpenSource!

Das sind doch mal hervorragende Neuigkeiten!

Microsoft hat im Rahmen seiner Online-Konferenz connect(); am Mittwoch bekannt gegeben, dass das komplette .NET Framework zukünftig als Open-Source-Software unter der MIT-Lizenz stehen wird.

Quelle: http://www.heise.de/newsticker/meldung/Microsoft-NET-wird-komplett-Open-Source-2452033.html

Das freut mich als Entwickler natürlich sehr. Dann können meine PI’s bald noch mehr durch Mono 🙂

Bisher wird per USB/RS232 der Stromzähler über die Infrarot-Schnittstelle ausgelesen 😉

Why I prefer WebApplication deployments over GAC deployments

This article is written with scope on SharePoint 2013. With SP 2013 the default TrustLevel in the web.config is set to “FullTrust”. On previous version the value is “WSS_Minimal”.

When you develop Farm-Solutions for SharePoint, you can deploy assemblies to the Global Assembly Cache (GAC) or configure the solution for a “bin-Deployment”.

The bin-way puts assemblies into the bin folder of the WebApplication, where the solution is deployed to.

You can switch the target of the assemblies by modifying the properties of a SharePoint project. The default value is GlobalAssemblyCache.

What does the changed property do to your solution?

Changing the value to WebApplication will deploy the assembly to the bin-directory of your IIS directory, as mentioned earlier. Because of the narrowed scope of the assembly, only the associated application pools needs to be recycled.

The classes you implemented, will be available only to your Website, which is fine in most cases. Assemblies within the GAC are available for all processes on the server.

In the past (prior SharePoint 2013) assemblies did not have FullControl permissions if they were deployed to the bin-directory. Instead Partial Trust was granted with the “WSS_Minimal” policy. A custom Code Access Security (CAS) had to be configured.

An advantage was the least privileges approach, a disadvantage the overhead of creating this CAS.

This is a list with advantages and disadvantages for bin-deployments. Pick your items and weight them the way you prefer.

My result was to deploy to bin, if possible. The faster development and deployment together with minimal impact on productive servers was worth it.

Advantages

  • Faster Deployment – With a GAC Deployment all application pools (incl. CentralAdministration) will be recycled
  • Less impact on other components

Disadvantages

  • TimerJobs need assemblies within the GAC
  • Using Feature Receivers, you’ll need to recycle the CentralAdministration application pool as well. Otherwise activating a Feature through the UI, could load the old assembly
  • Only one version of an assembly

What do you think? Why do you deploy to bin or to GAC?