Radi Atanassov

SharePoint MCM, MVP, MCT and owner of OneBit Software

Azure App Service CORS versus Web API CORS

I'm blogging this as it wasted about 3 hours of my time. I ended up debugging the Microsoft.AspNetCore.Cors library, and that takes time.

I was having issues with cross-domain AJAX requests (with AngularJS). Firefox was pretty shit at telling me the problem. The developer tools just show the failed request. IE was pretty verbal:

SEC7122: Credentials flag was set to true, but Access-Control-Allow-Credentials was not present or was not set to "true".

Right on the spot. So using Fiddler, I spent some time reviewing HTTP packets (of course it is difficult with HTTPS and debugging) and IE was pretty much right. The response did not include Access-Control-Allow-Credentials: true

I tested it locally and it works fine. Debugging runtime in Azure is difficult (I would've lost another 3 hours probably) so I ended up guessing. It turns out that configuring CORS on the Azure Web Site overrides stuff in the underlying layers. Even though that ASP.NET Core is doing the right thing, somewhere (most likely on packet exit) Azure CORS takes control. So, if you want to use CORS in ASP.NET, avoid this:

Solution: remove all of them, including a "*" if you have one.

Unfortunately (for me), this is also documented (I went to document it myself, but it was already there!). All I had to do was find it :)

https://azure.microsoft.com/en-gb/documentation/articles/app-service-api-cors-consume-javascript/#app-service-cors-versus-web-api-cors clearly states:

"Don't try to use both Web API CORS and App Service CORS in one API app. App Service CORS will take precedence and Web API CORS will have no effect. For example, if you enable one origin domain in App Service, and enable all origin domains in your Web API code, your Azure API app will only accept calls from the domain you specified in Azure."

And even further, there is something on StackOverflow:

http://stackoverflow.com/questions/36860423/enable-access-control-allow-credentials-header-in-azure-website-azure-app-servi

Ouch, painful, lesson learnt. Hope this helps you and saves you time.

For the record, Microsoft.AspNetCore.Cors ignores everything if the Origin header is not present:

Microsoft.AspNetCore.Authentication.ActiveDirectory updated to ASP.NET Core RTM

Since the ASP.NET Core RTM bits came out it's time to update all RC1/RC2 solutions and NuGet packages to run under RTM.

Find it here:

The steps to update are not that difficult, but here they are in general:

  1. Global.json should be updated, and the version here is important. Notice the bits are in preview (we still don't have VS2015 tooling that is RTM at the time of writing this):
{
"projects": [ "src" ],
"sdk": { "version": "1.0.0-preview2-003121" }
}
  1. Change all dependencies from Microsoft.AspNet.Something to Microsoft.AspNetCore.Something. Some libraries have been totally rearranged.
  2. Update the project.json file. There are quite a few things to be done and intellisense is good at pointing them out. The most important:
"frameworks": {
"netcoreapp1.0": {},
"net451": { }
}

This essentially means the library can run in both frameworks, cool.

The code has also significantly changed/improved – lots of work around redirects and working with the ASP.NET Cookie Middleware.

Feel free to ping me if you have issues.

Getting Started with ASP.NET Core Add-ins for SharePoint Online

Overview

With the introduction and growth of ASP.NET Core, we SharePoint/Office 365 developers need a story that allows us to build Add-ins on top of provider-hosted ASP.NET Core deployments. What we have now works with old school ASP.NET and MVC 5 (yes, that is now old J).

As I explained in my previous post, Developing the ASP.NET Core Authentication/Authorization Middleware for SharePoint Provider-Hosted Apps (Add-ins), I've explained why this might be appealing and the technical challenges we are faced with. I have put together a library that allows us to develop SharePoint Add-ins that run on ASP.NET Core and in this blog post I explain how you can get started with including it in your own ASP.NET Core projects.

We have now updated the library to .NET Core and ASP.NET Core RTM. Previously it was running on RC1 only.

If you just want to have a look, just get the sample project and run it. Please share your experiences and feedback, they are an important reminder to where we need to put effort in with the PnP team.

Before you start

  • You don't have to complete these steps manually; the PnP repository has a sample project located here: https://github.com/OfficeDev/PnP/tree/master/Solutions/AspNetCore.Authentication
  • Make sure you are using Visual Studio 2015 Update 3. This is not required, but some new features in the tooling make things easier.
  • You need to register your app and get a ClientId and ClientSecret. This is not detailed here as it is nothing new. By default, ASP.NET Core web applications run on https://localhost:5000

Things you need to know before you start (all are explained why here):

  • At the time of writing (09.09.2016) there is no support for High-Trust Add-ins, yet. This is on our roadmap.
  • Our PnP library still targets .NET Framework 4.5.1.

Adding SharePoint Authentication to ASP.NET Core

Step 1: Create a new ASP.NET Core project based on the Web Application template

Step 2: Change the target framework of the web application project

This might change in future. Currently, our PnP library only runs on .NET 4.5.1. See why in this post: Developing the ASP.NET Core Authentication/Authorization Middleware for SharePoint Provider-Hosted Apps (Add-ins)

Change this:

"frameworks": {
"netcoreapp1.0": {
"imports": [
"dotnet5.6",
"portable-net45+win8"
]
}
},

To this (you can, of course, keep the imports that you need):

"frameworks": {
"net451": {}
},

Then, remove the dependency to Microsoft.NETCore.App (it is only for netcoreapp1.0 and above):

"dependencies": {
"Microsoft.NETCore.App": {
"version": "1.0.0",
"type": "platform"
},

If you need the NETStandard library , just add it under dependencies:

"dependencies": {
"NETStandard.Library": {
"version": "1.6.0",
"type": "platform"
},

Step 3: Add the Microsoft.SharePointOnline.CSOM NuGet package

You need this to write SP CSOM code that works with SharePoint J Get it here: https://www.nuget.org/packages/Microsoft.SharePointOnline.CSOM/

PS Command: Install-Package Microsoft.SharePointOnline.CSOM

 

Step 4: Add the OfficeDevPnP.Core.Framework.Authentication NuGet package

With the current release of VS Tooling and .NET Core projects (Preview 2 at the time of writing) you can't add a reference to a DLL, you need to add it through a NuGet package.

As pointed out, also at the time of writing the PnP Core Authentication code is not part of the Core library (see roadmap later in this post, we are working on that). This means that you need to bundle the OfficeDevPnP.Core.Framework.Authentication DLL into a NuGet package.

You can do this following the steps outlined on the NuGet site (https://docs.nuget.org/create/creating-and-publishing-a-package ) or just using Nuget Package Explorer (click here).

 UPDATE (18.09.2016):

I have added a ready NuGet package to the project. You can find it here:

 

Step 5: Add other necessary NuGet packages to your project.json

You will need these:

"Microsoft.AspNetCore.Authentication": "1.0.0",
"Microsoft.AspNetCore.Session": "1.0.0",
"Microsoft.AspNetCore.Server.Kestrel.Https": "1.0.0",

 

Step 6: Configure your Service Collection and pipeline in Startup.cs

Now it is time to add code. I hope you are impressed with the minimal footprint.

Add using OfficeDevPnP.Core.Framework.Authentication; and using OfficeDevPnP.Core.Framework.Authentication.Events;.

Include AddSession() and AddAuthentication() to your service collection.

public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddMvc();
 
//Add Session to the service collection
services.AddSession();
 
//add the authentication middleware and point SP as the default authentication sign-in scheme
services.AddAuthentication(sharedOptions =>
sharedOptions.SignInScheme = SharePointAuthenticationDefaults.AuthenticationScheme);
}

Then, go ahead and configure your pipeline to include the middleware:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
//required to store SP Cache Key session data
//must also call AddSession in the IServiceCollection
app.UseSession();
 
//Add SharePoint authentication capabilities
app.UseSharePointAuthentication(
new SharePointAuthenticationOptions()
{
ClientId = Configuration["SharePointAuthentication:ClientId"],
ClientSecret = Configuration["SharePointAuthentication:ClientSecret"],
 
AutomaticAuthenticate = true, //set to false if you prefer to manually call Authenticate on the handler.
//OPTIONAL: CookieAuthenticationScheme = "AspNet.ApplicationCookie",
 
//Handle events thrown by the auth handler
SharePointAuthenticationEvents = new SharePointAuthenticationEvents()
{
OnAuthenticationSucceeded = succeededContext => {
return Task.FromResult<object>(null);
},
OnAuthenticationFailed = failedContext => {
return Task.FromResult<object>(null);
}
}
}
);

NOTE: Some web applications/add-ins will require multiple authentication mechanisms. The library is built to allow this and co-exist with other Authentication middleware.

NOTE 2: Keep in mind that this is a pipeline, so order matters. The right place will depend on your app.

 

Step 7: Add your ClientId and ClientSecret

Configurations in ASP.NET Core happen in the appsettings.json file. Add the following under the root object:

"SharePointAuthentication": {
"ClientId": "Add id here",
"ClientSecret": "Add secret here"
}

Step 8: Modify your Kestrel Web Server to run on HTTPS

Since we're doing Add-in authentication based on the OAuth protocol, we need to run over SSL. ASP.NET Core can run both on IIS and on Kestrel, I prefer Kestrel. This is what you need to do:

In Program.cs, change this:

public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
 
host.Run();
}

To this:

public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseKestrel(options =>
    {
    options.UseHttps(@"..\..\certificates\localhost_ssl.pfx", "pass@word1");
options.NoDelay = true;
    }
)
.UseUrls("https://localhost:5000")
.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup<Startup>()
.Build();
 
host.Run();
}

You can stick it in a try/catch if you wish. I have also added a IgnoreSslErrorsConnectionFilter class in the PnP sample to get rid of SSL handshaking errors with untrusted certificates. This is optional.

The SSL certificate is committed to the certificates folder. Note the https://localhost:5000 URL. Make sure everything runs at this point.

Make sure your project is firing up HTTPS://localhost:5000 and your F5 is not kicking off IIS Express, but rather the actual web application (which runs it as a console application now). This will start Kestrel.

Step 9: Add some CSOM code

You are all set. Write some CSOM Code to test:

var spContext = SharePointContextProvider.Current.GetSharePointContext(HttpContext);
var spLists = new List<SharePointListViewModel>();
 
if (spContext == null) return View();
 
//build a client context to work with data
using (var clientContext = spContext.CreateUserClientContextForSPHost())
{
if (clientContext != null)
{
var lists = clientContext.Web.Lists;
clientContext.Load(lists);
clientContext.ExecuteQuery();
 
foreach (var list in lists)
{
spLists.Add(new SharePointListViewModel() { ListTitle = list.Title });
}
}
}

Step 10: Test it!

Now that everything is set, go to the SharePoint Online site where your app is configured, then click it's link. It will go through AppRedirect.aspx and then lead your browser to https://localhost:5000 if everything is configured right. The ASP.NET Code PnP middleware will intercept (based on the SPHostUrl query string) and get the context token, work through it and eventually allow you to instantiate the SPContext object needed to work with CSOM data. Pretty cool, hey?

Summary

Overall, it takes 10 steps to heaven J We are working hard to improve everything we can in regards to the developer experience, that is the fun parth in building tooling and API's.

Please take the time to give feedback, share your issues or even high five. Microsoft and the PnP team need to see activity and the need for this library, so we have justification to increase its priority.

 

Roadmap for the ASP.NET Core Authentication library

As mentioned, things are still evolving. We have tons of issues to solve in terms of dependencies and figure out how to make it easier to plug-and-play all of this. It might seem hard at first, but so where Apps when they first came out. The PnP team is working hard to make it easier for developers and this is all done in our free time. Please help us out with constructive feedback and contributions https://github.com/OfficeDev/PnP .

Here is a list of targets that we have:

  • Enhance the sample to demonstrate the usage of App-Only access tokens.
  • Enhance the sample to demonstrate on-the-fly authentication through the Authentication Code flow.
  • Remove dependencies from Microsoft.IdentityModel.Extensions and framework assemblies
  • Implement High-Trust authentication capabilities
  • Add to the current OfficeDev PnP Core library
  • Build a true .NET Core App compatible library

 

Team Leadership in а Software Development World

Being a good team leader is hard. At least for me. For some it may come natural, for others - we have to put in a reasonable amount of effort to get it right. I spend a lot of energy thinking about what good leaders do, especially in the software development field, so I'm putting forward some thought and principles that I follow. Read further for my ideas to grow software development team leadership into a workable model.

Team leadership is different from management. It's less bullshit, more personal and very tactical, operational and actually things get delivered. That's why it's important. I'm going to start writing a series of posts about it and this is the first one. I'm sharing my key principles, which are written from a software development perspective, but most apply to any industry. Principles are essential towards establishing the grounds of an initiative. They are personal, but everyone can interpret them from their point of view (see measurement below, there is no black and white here.). You'd be surprised at how many teams don't even have principles.

The actual real-life problem

No one teaches us to be team leaders. We either get promoted to the position at one point in our careers, or we do the job because we stood out. Every available courseware on team leadership is part of some greater initiative, so learning is not really focused. You can even argue that there isn't really any good courseware on team leadership, especially in the software development space, yet there are millions of team leaders around the world. There's books, but that's different, you need practical workshops that take days, but we rarely do those. Very little companies offer soft-skills and management training, and usually the "team leader" is in that middle ground between management and developer, so they don't really get the training attention. The second part to the problem is that team leaders are naturally busy and many companies don't invest in that training level.

Creating a methodology

I believe the entire practice of team leadership could be put to a model. This is not a software delivery model or a project life-cycle methodology, but rather a framework for learning about and growing team leadership skills. I don't have the experience to do it in the context of other disciplines, but hopefully I have the experience to base it on software development. Maybe I suck at it, but at least I'm doing something about it. Do you want to help me write/author this model? I am gathering a team to work on this side project, so let me know if you are interested to help out and be part of it. I'm even keen to hear if you are just interested in this model and you think it is a good idea.

Here are things I try to be best at.

Knowing your team

I try to get to know everyone as much as I can, but not crossing the line where you become too close (dangerous). Go to lunch together, socialise and listen. Observe. There is huge value in listening alone. Spending out-of-office time with the team allows people to open up. Understanding the true character of your team members by talking to them is very important. Stories and experiences are usually shared outside of the work environment, so whatever you could fit in is worthwhile. I use this time to get a feel of people's behaviors, preferences, their most productive time of the day, whether they are introverts or extraverts, whether they have problems that I could be aware of (and maybe help), how they communicate, sometimes you might even pick up on how they solve problems or resolve conflicts. All this information is extremely valuable to me - I can arrange people with similar productivity patterns, I can reduce the stress if there are issues on the side, I can learn about things in our work environment, I can show personal interest and that really matters, it is well respected. It might not always be lunch - drinks after work or anything else you could think of will do. This point proves that work and life are actually things that go together, and they need to be balanced.

Key point: Get them to know you too. Tell your stories. You are their leader, so opening up could really go a far way.

Understand the "TEAM" part in "team leader"

No one gets big results done when working alone, and we usually want big results out of our jobs, lives and ideas. A team leader who does all the true work is pretty much a failed team leader. Results (and innovation) get delivered and nurtured when many people work together for the common goal. This is why we have teams in the first place. I do the best I can to fairly share the work and make sure everyone is putting in their part. This doesn't always work, sometimes the key foundations of what the team is doing misaligns with members of the team. But at the end of the day results happen when everyone contributes.

Agree on principles

Yes, that's one of my principles J This is actually applicable for all situations when you do something with someone else - love life, project work, company management, many others but also working in a team. You define and agree on the team's key principles so everyone knows which direction to follow, how to go by it, and most importantly, how to resolve a conflict when you need to. You base decisions and resolutions on your principles - that is a good and easy way to solve issues related to personal preferences.

Lead.

Quite a no brainer, but you have to lead people. Many misinterpret what leading actually is. To me it is not about giving tasks or solving their technical challenges, it is about empowering people to figure out and perform their own tasks in the best direction for the situation. Instead of solving the most technical challenges, give directions and guidance so the team members solve their technical challenges, offer support and re-evaluation when needed. This principle touches on the management side of things, but reading between the lines it is different. You will find many "Leader vs. Manager" comparisons to include this.

Give feedback often

I suck at this and I am working on improving it, and adopting it as a principle is the first step in improving it. Giving positive feedback is much easier, giving negative feedback in a timely manner is critical, but for some it is really difficult. If you don't do it your team members will think that what they are doing is right and exactly what you expected, yet you don't get the results in. Giving positive feedback is equally important, but much easier to learn and get into a habit. Negative feedback I always in private, positive feedback – always public.

Respect what you do

Show that you care, both about the people and the actual work that you do. Promote the idea of mutual respect as well as respect for the work that you do, highlight it as a principle. You can show respect in many ways, here's a few tips: Listen to personal issues and give advice on how to minimize their impact on the whole team. Motivate team members to respect the team as a whole, in general, and believe in the work that you do. That is very important. I sometimes have projects that I don't really believe in - they either don't bring value or the requirements are just silly. It is extremely evident when people have to do things they don't believe in. When a team leader doesn't care - things go downhill. I have seen this with some of our work and it's not good. A good team leader will find a way to make everything appealing to the team so the work is done with quality in mind. Quality leads to happy team members, happy clients and long-term success. We often have to do work that we don't like or don't want to do. Those emotions are best kept aside and often they are for a greater cause, so do your best to respect that work too.

Minimize process and paperwork

Being lean is good and I have had really good results here. Other companies and team leaders praise OneBit for being so lean and fast. A true leader removes obstacles from interfering with the true work that delivers value. Team members appreciate when you make their job easier. Do whatever you can to simplify what they do and how they need to do it. This is important for the people that actually get things done. Get rid of process. Don't give me the "we're a large organization with slow processes and lots of approvals" bullshit, I've heard it way too many times. You're a team leader, you're there to make things happen, so change your business and stop saying "that's how our slow company does things". People will leave you if they have far too much stuff that impedes their work, and if they leave - you have no team and you're not leading anyone. Developers are smart - they want to code at least 40 hours a week, not 20 and spend the rest in processes and impediments. Being lean should be a principle.

Be a good human

A colleague of mine praised me with a few simple words - he used that term - "good human". It stuck with me, but I could actually relate to it significantly. I'm taking it in as a principle. I don't know how to define what it is to be a good human, but I'm doing my best to be one in my own perception and character. You can take it under your own understanding and mark it down based on what you feel is good, I focus on fairness, being nice, supportive, having values and avoiding anything that makes me look like an asshole. I've got lots of those.

Be up to date with your stuff

You might not be in the software development field, but I'm sure this relates to you. IT is an industry and ecosystem that changes constantly. I've adopted the concept of working 24/7 and I am perfectly fine with that. If I'm not in front of a device, I observe and learn about human behavior, social patterns, how to be a good human and sink in any information I find relevant from everywhere (that is what I mean when I say 24/7). On the technical side, you should really be well up to date and actually top notch with what you do. Adopt it as a principle to know as much as you can. Some team leaders fall behind with the latest trends and innovations, but other jobs just demand you to be the best. Mine does so I do everything I can here.

Measurement

I try to measure everything I do. Everything from where my time is wastes to how much water and electricity I use. Measuring the performance of a "team leader" is hard and subjective. It's also quite difficult to define what "getting it right" actually means. There is no black and white, it is all about you and your team, and how you do what you do together. Most books specify that KPI's should be related to staff retention, growth, numbers, and many other measurable indicators. While all that is true, I try to never underestimate or forget about the bond with your team. The level of mutual respect, loyalty, trust and support. You can't really measure that. Managers measure KPI's, team leaders focus on the unmeasurable relationships between people. It takes time, sometime years, to build this and you never know if you're there or not

That's all for now.

 

Last words

I'm working on ways to enable better learning of team leadership. For now – all I have to offer is learning through experience. My amateur way to recruit a good team leader: join me J Let me know you want to be a good team leader and let's both learn how to be good team leaders together. That's probably the best opportunity you have in front of you and these last sentences are the best I could do at subliminal advertising. Thanks for reading :)

Developing the ASP.NET Core Authentication/Authorization Middleware for SharePoint Provider-Hosted Apps (Add-ins)

Getting SharePoint apps to work with ASP.NET Core was a bit of an interesting challenge, which I will share with you in this post. A nice new addition to the Office Dev PnP repository surfaced up from getting this working – a library/implementation for you to reuse in your day-to-day ASP.NET Core apps/add-ins development (see https://github.com/OfficeDev/PnP/tree/master/Solutions/AspNetCore.Authentication). You add this to your ASP.NET Core projects and you can authenticate as a SharePoint provider-hosted app. Hopefully, we will integrate this into the PnP Core namespace & package as the time comes.

The Problem

In order to build ASP.NET MVC 5 apps (not ASP.NET Core) we have the option to use the Office Developer Tools for Visual Studio 201X, which gives us developers an "App for SharePoint" project template (notice the App terminology never changed to Add-ins!). We create one of these and get an ASP.NET MVC 5 web application project together with an App project with the manifest and packaging capabilities. We get files such as TokenHelper.cs, SharePointContext.cs and SharePointContextFilterAttribute.cs with all the plumbing for token requesting, storage, cookie generation and authorization. Good stuff, but now old.

We currently don't have an equivalent for ASP.NET Core. There is no toolset in Visual Studio to develop apps/add-ins that run on ASP.NET Core, no project template. I have asked Microsoft around and as far as I got responses there is no team assigned to develop anything. The guy who developed the toolset moved on to another team. What's even more complicated is the fact that ASP.NET Core is drastically different, so we can't just do a copy/paste port and recompile it for the DNX runtime. We have to rewrite the whole implementation.

This blog post is my story on the rewriting of it and bringing the SharePoint developer community a way to do SharePoint apps with ASP.NET Core.

Business Justification

Why would you use ASP.NET Core for SharePoint Apps?

  • You may want to migrate existing ASP.NET MVC 5 Provider-Hosted Add-ins to ASP.NET Core to make use of the benefits that the new platform offers
  • Introduce an ASP.NET Core / SharePoint Add-in story, because currently there is none. PnP to the rescue!
  • You might not be ready for Azure AD authentication and the Active Directory Authentication Library (or you just don't want to use it for whatever reason, such as the new MSAL package)
  • You want your provider-hosted Office Marketplace app to use ASP.NET Core.

The Solution – PnP to the Rescue!

The actual solution to the above problem is quite simple:

  • create a library that performs the necessary authentication handshaking and authorization to be able to run SharePoint apps/add-ins on ASP.NET Core.
  • Bundle it as part of PnP so it gets adoption, attention, contribution and support
  • Publish it as a NuGet package so everyone could add it and use it in their ASP.NET Core web applications.

Some terminology to clarify things:

  • AspNetCore.Authentication – this is the name of the Office PnP Solution in the repository. It contains a sample web application, a SharePoint app project and the library below
  • OfficeDevPnP.Core.Framework.Authentication – the name of the library (and namespace) with all of the authentication logic & plumbing. This is what will be pushed out as a NuGet package so it can easily be added to any ASP.NET Core project.

Design Goals

I've used the following principles and goals in the design of this solution:

  • It must be very easy to "Add" and "Use", based on the plug 'n' play model of ASP.NET Core (Add and Use are special Core terms)
  • Enforce the least amount of change to the developer experience, SharePoint developers should know how to use this straight away
  • Base it on the ASP.NET Core middleware design
  • Figure out how to compile to DNX Core. This is currently not achieved. We must compile to .NET Framework rather than Core due to a dependency on Microsoft.IdentityModel.Extensions.dll
  • Implement with ASP.NET Core configuration and logging patterns/classes
  • Base it on the ASP.NET Authorization & Authentication model so the request is truly authenticated and authorized from the System.Security.Claims.IIdentity perspective.
  • Be able to use the [Authorize] attribute to lock down controller methods
  • Figure out how to include it as part of the OfficeDevPnP.Core library. This is currently not achieved. We cannot add it to the true Core assembly due to the old project format and the fact that we're using the/ DNX assembly format.
  • Release it through NuGet so anyone could add it to their ASP.NET Core web application.

How does SharePoint Authentication/Authorization work in the ASP.NET MVC 5 implementation?

When we are tackling a port/upgrade/rewrite of something we must really understand how it works to build on it, improve it and get results. This is a quick refresher of how SharePoint provider-hosted authentication is implemented in ASP.NET MVC 5.

  • We had tooling, the Office Developer Tools for VS, which gave us a starter template project with several class files that made authentication work with SharePoint.

  • From that point onwards we literally press F5 and VS does what it needs to do to get a "Hello World" solution running. It worked.
  • The TokenHelper.cs & SharePointContext.cs set of classes handled the required plumbing & business logic.

  • These classes had a dependency on Microsoft.IdentityModel.Extensions.dll for S2S and OAuth2 token/claims manipulation.
  • The class design and implementation followed the MVC 5 patterns and development model
  • We had a publish & deploy experience, quite satisfactory for most.
  • A SharePointContextFilter attribute handles redirects and retrieves a SharePointContext object in session.
  • The SPCacheKey is stored in a cookie to identify users between their redirects and web requests
  • TokenHelper deals with authorization codes and access tokens, together with Microsoft.IdentityModel.Extensions.dll
  • The SharePointContext.cs file contains a total of 7 classes, some of them abstract. SharePointAcsContext/Provider and SharePointHighTrustContext/Provider are important as they hold the specific implementations of authentication through ACS and through the High-Trust model (using symmetric keys from certificates).
  • When the user clicks on an installed app url, or the app icon on the site contents page in SharePoint, the user is taken to AppRedirect.aspx. This page generates an HTML form element posting to the URL of the app, providing it with a context token and other useful information so the provider-hosted app can authenticate the request. I will not go into greater detail of this process, but it is crucial to understand it. It is well documented by fellow bloggers.
  • There is no true implementation of ASP.NET authorization (the [Authorize] attribute) at the MVC controller level. Poo.

NOTE: The above are key points that describe how the AuthZ mechanism works when we talk about SharePoint Provider-hosted apps. Note that it is truly authorization, not authentication. SharePoint handles authentication through its identity provider, then OAuth is used to share resources between SharePoint and the application you are building. OAuth 2 is an authorization protocol (see https://tools.ietf.org/html/rfc6749). On this point, read further down for some wording misnomers…

ASP.NET Core Implementation Deep Dive

OK so here we go. So far it is called AspNetCore.Authentication, which is probably the name that will last for a while until Vesa makes me change it. In the following section I list the key implementation decisions made so far. Here is a quick screenshot of the classes created to meet our needs:

Middleware

It is based on the ASP.NET middleware concepts, registered through extension methods on the IApplicationBuilder object during the Configure method in Startup.cs

//Add SharePoint authentication capabilities

app.UseSharePointAuthentication(

new SharePointAuthenticationOptions()

{

CookieAuthenticationScheme = "AspNet.ApplicationCookie",

//I really don't like how config settings are retrieved, but that is how the ASP.NET guys do it in their samples

ClientId = Configuration["SharePointAuthentication:ClientId"],

ClientSecret = Configuration["SharePointAuthentication:ClientSecret"],

//Handle events thrown by the auth handler

Events = new SharePointAuthenticationEvents()

{

OnAuthenticationSucceeded = succeededContext =>

{

return Task.FromResult<object>(null);

},

OnAuthenticationFailed = failedContext =>

{

return Task.FromResult<object>(null);

}

}

}

);

 

Authentication & Authorization

The AspNetCore.Authentication library is based on the Authentication & Authorization libraries part of ASP.NET Core (see https://github.com/aspnet/Security/tree/dev/src/Microsoft.AspNetCore.Authentication and https://github.com/aspnet/Security/tree/dev/src/Microsoft.AspNetCore.Authorization ). This is important to achieve one of the design goals – consider the web request authenticated and be able to use the [Authorize] attribute and relevant AuthZ capabilities.

The provided SharePointAuthenticationMiddleware class inherits the framework's AuthenticationMiddleware class

public class SharePointAuthenticationMiddleware : AuthenticationMiddleware<SharePointAuthenticationOptions> { …removed… }

The CreateHandler method returns an instance of the SharePointAuthenticationHandler, holding all of the logic for authentication handler:

protected override AuthenticationHandler<SharePointAuthenticationOptions> CreateHandler()

{

return new SharePointAuthenticationHandler();

}

NOTE: Back to the point on AuthZ vs AuthN, the ASP.NET classes use the Authentication term, even though there is a case where a remote party does the authentication. This might be a topic for argument for the purists and scientists out there.

Cookies and Session

The cookie handling implementation has been entirely rewritten in ASP.NET Core, so naturally that had a knock-on effect on the SharePointContext classes in AspNetCore.Authentication that manage the cookie to track the user's requests.

//The following code generates a cookie in the response with the SPCacheKey as a value

var options = new CookieOptions() { HttpOnly = true, Secure = true };

httpContext.Response.Cookies.Append(SPCacheKeyKey, spAcsContext.CacheKey, options);

//read the cookie value

HttpCookie spCacheKeyCookie = new HttpCookie(SPCacheKeyKey, httpContext.Request.Cookies[SPCacheKeyKey]);

string spCacheKey = spCacheKeyCookie != null ? spCacheKeyCookie.Value : null;

Luckily, the code is pretty simple J

Handling Events

In a typical use-case scenario, you would reference the compiled library and retrieve it through the NuGet package manager. That means that you can't really plug in your own code, so I've implemented an events model. The idea is that you as a developer will subscribe to the events and deal with custom logic in the handlers. The following are the currently implemented events:

/// <summary>

/// Invoked when the SharePoint authentication process has succeeded and authenticated the user.

/// </summary>

public Func<AuthenticationFailedContext, Task> OnAuthenticationFailed { get; set; } = context => Task.FromResult(0);

 

/// <summary>

/// Invoked when the authentication handshaking failed and the user is not authenticated.

/// </summary>

public Func<AuthenticationSucceededContext, Task> OnAuthenticationSucceeded { get; set; } = context => Task.FromResult(0);

See the Events = new SharePointAuthenticationEvents() { } line in the UseSharePointAuthentication extension method.

 

Let me know if you need any other events handled.

Getting Started

So, to get this up and running, do the following:

  1. Clone and build the OfficeDevPnP.Core.Framework.Authentication project and add a reference to the output NuGet package to your ASP.NET Core application.
  2. Add the following to the Startup.cs Configure method in your ASP.NET Core web application:

app.UseSharePointAuthentication(

new SharePointAuthenticationOptions()

{

CookieAuthenticationScheme = "AspNet.ApplicationCookie",

ClientId = Configuration["SharePointAuthentication:ClientId"],

ClientSecret = Configuration["SharePointAuthentication:ClientSecret"],

}

);

 

  1. The library needs Session and Cookies in order to keep track of the client requests during redirects. Add the following to the Configure method:

app.UseSession();

 

app.UseCookieAuthentication(new CookieAuthenticationOptions()

{

AutomaticAuthenticate = true,

CookieHttpOnly = false,

AutomaticChallenge = false,

AuthenticationScheme = "AspNet.ApplicationCookie",

ExpireTimeSpan = System.TimeSpan.FromDays(14),

LoginPath = "/account/login"

}

);

Note that the AuthenticationScheme must be the same in both Use instructions. This is so the SharePointAuthenticationHandler also signs in the cookie authentication middleware to issue the needed cookie.

  1. For the Session & Cookie pipeline additions to work, the following needs to be added to the ConfigureServices method of Startup.cs:

services.AddCaching();

services.AddSession(o => { o.IdleTimeout = TimeSpan.FromSeconds(3600); });

 

  1. There's a few other intricacies in the whole setup:
    1. HTTPS – the web server must be serving over HTTPS. See the sample project for an example of setting up Kestrel with SSL
    2. Bower and NPM – if you are looking at the AspNetCore.Mvc.StarterWeb project you might need to restore all packages to get it running.

That should do it!

Frequently Asked Questions

What about UseRemoteAuthentication?

The ASP.NET Core authentication library/package (Microsoft.AspNetCore.Authentication) has a sample implementation of "Remote" or "External" authentication, packaged in a RemoteAuthenticationHandler class. I spent a good amount of time researching those at the time of writing this library, however I came to the conclusion that it is way too soon to use those classes. It was heavily changed/updated and not stable/ready enough to use when I needed it.

While it sounds like the perfect way to achieve what we want, for the time being I've kept away from it. I will keep a very close eye and rewrite the implementation if required, when we have something stable to work with.

What about Microsoft.IdentityModel.Extensions.dll?

This one's a bit of a bitch. I've posted a question to the relevant Microsoft team to understand what the next plans for this library are and got this for an answer:

"We have moved forward on S2S specific libraries, but it is too early to share publically" (see https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/343 )

Not really satisfactory,but at least it is something, so I made the decision to just reference it for the time being until there's new things coming.

The negative effect on the OfficeDevPnP.Core.Framework.Authentication library is that we must compile to the .NET Framework rather than .NET Core since it is compiled for .NET 4.5.2, but that is not such a huge issue because the CSOM library is in the same boat. Until both implementations are ready for .NET Core we will have to live with the fact that we're compiling for the full framework. I'll be working on communicating with the right people on the needs and challenges here.

I'm also looking at the option to completely rewrite the GetAccessToken() methods in TokenHelper.cs, replacing all instances of OAuth2S2SClient and similar classes with custom ones, or reuse some if Microsoft do something in this space. This will allow us to ditch this damn library.

What about compiling for .NET Core?

We're gonna have to recompile the Microsoft.SharePoint.CSOM.dll library for this. It's too big of a task for me (having to run OneBit Software in my work time), but maybe with the PnP folks we can lobby Microsoft to do it, or just recruit more lads and las to help us out. Currently, it is not on the immediate priority list, but I would love to do this one day.

Will this have Visual Studio tooling?

At this stage there are no plans for this, given that the actual app manifest project is still completely operable and you can use it as you always have. If you check out the ASP.NET Core model, things are a bit different now. You add your minimum amount of NuGet packages that you need through the dependency section in the project configuration file and the package manager interfaces, and you only get what you need. ASP.NET Core is minimalist and cool.

In that sense, my goal is to host OfficeDevPnP.Core.Framework.Authentication as a public NuGet package and allow you to directly add it as a package, when you need it. Just like the ASP.NET Core model.

What about a pure client-side implementation?

No. Not here. The SharePoint provider-hosted AppRedirect.aspx mechanism is based on the OAuth 2 Authorization Code flow, which is not safe if the required tokens are transferred to the client. (For more details see my slides from the Azure AD workshop that I delivered in Lisbon).

A client-side authentication implementation must use the OAuth2 Implicit Grant flow, with is specifically designed for those use-cases. It is only as secure as the browser's capability to secure Local Storage and cookie jars.

If you are looking for a pure JavaScript client-side implementation, see the ADAL.JS library and its implementation for AngularJS, but make sure you are aware of its flaws with IE and trusted zones.

Why do you have Gulp, Bower and NPM in the sample StarterWeb project?

The design goal of the sample web application was to use the ASP.NET Core Web Application project template and only add what is needed to demonstrate SharePoint provider-hosted authentication. It comes with all those goodies, so I prefer people to see the difference between a new project and the AspNetCore.Mvc.StarterWeb sample project, and decided not to remove them. People should get to know that stuff.

Future Plans and Upcoming Tasks

Here is a quick summary of what changes are being planned and worked on:

  • Get it working with RTM, I'm waiting for updates on the ASP.NET authZ/authN libraries to figure out if any real architectural changes are required
  • Decide on the High Trust story – we (PnP) still don't know if it is important, so bug us if it is!
  • Decide on the overall PnP strategy for ASP.NET Core, because this is the first solution/sample/component that is built on ASP.NET Core
  • Decide if we need to get some VS tooling to work with this library

Thank you for reading this far (if you actually did!) and thanks to all of my Stockholm SharePoint friends for giving me the motivation to write this blog post on my flight back from SPS Stockholm. Tell Vesa that this stuff is important so we lift it up in the priority list J

A HUGE thanks to Velin Georgiev from OneBit Software for helping me code this up.

Using ASP.NET Identity 3 with Entity Framework 6

Overview

 

I put together a provider for Entity Framework 6 and ASP.NET Identity 3. This post introduces it.

ASP.NET Identity 3 is awesome and packed with new features. Me and my team (OneBit Software) – we are comfortable and very keen to use it in our projects.

ASP.NET Identity 3 by default uses Entity Framework 7 (together with other details, such as ASP.NET 5, MVC 6, DNX, etc. etc.). EF7 is also great and stable, but very feature-poor at the moment. We are not ready to use EF7 (at the time of writing this post) in production, even though there is go-live production support for it.

Entity Framework 6 for that matter is stable and we trust it.

So the long story short – we need ASP.NET Identity 3 with support for Entity Framework 6. The solution is the Microsoft.AspNet.Identity.EntityFramework6 project.

GitHub source: https://github.com/OneBitSoftware/Microsoft.AspNet.Identity.EntityFramework6

At the time of launching the project is built for RC1-Update1. All nugget packages are fixed to the 1.0.0-rc1-final version.

The solution is structured with the core source, unit tests and a sample web application:

 

Entity Framework 6

 EF6 doesn’t support generic types for DbSet’s. You can’t do:

 DbSet<IdentityUser<TKey>> Users;

 This adds some complexity, because Identity 3 aims to use generic types to support generic keys for the database.

 There’s some further complexity in other features/limitations of EF6 in itself, so some parts of Identity 3 code need tweaking, like the OnModelCreating initializer.

 

ASP.NET Identity 3

 I’ve spent quite some time with this lovely library that it has become my weekend hobby. I’ve done my best to reuse as much as I can and do as little as possible to get it running with EF6.

 The database is assuming the Id columns (TKey) are of type string. You can modify that to your liking. I’ve done it because the default implementation uses Guids.

 There are no changes to the way ASP.NET Identity 3 works internally, all modifications are around how users and roles are stored.

 

Getting Started: Sample ASP.NET 5 MVC 6 solution project with ASP.NET Identity 3 and Entity Framework 6

 You will find a complete sample with everything set up in the repository: https://github.com/OneBitSoftware/Microsoft.AspNet.Identity.EntityFramework6/tree/master/samples/IdentitySamples.MVC6.EF6

 If you need to add this to your own MVC project, just reference Microsoft.AspNet.Identity.EntityFramework6 and place the following in the ConfigureServicesmethod of your Startup.cs file:

 //Inject ApplicationDbContext in place of IdentityDbContext and use connection string

 services.AddScoped<IdentityDbContext<ApplicationUser>>(context =>

     newApplicationDbContext(Configuration["Data:DefaultConnection:ConnectionString"]));

 

//Configure Identity middleware with ApplicationUser and the EF6 IdentityDbContext

 services.AddIdentity<ApplicationUser, IdentityRole>(config =>

 {

     config.User.RequireUniqueEmail = true;

 })

 .AddEntityFrameworkStores<IdentityDbContext<ApplicationUser>>()

 .AddDefaultTokenProviders();

  

 You can use ApplicationUser and IdentityDbContext to modify the model further.

 This is currently not released as a Nuget package, although if there is interest we could do that on MyGet.

 Dependencies

 The Test project requires Microsoft.AspNet.Testing and Microsoft.AspNet.Identity.Test nuget packages. These are available on the MyGet aspnetmaster package source here: https://www.myget.org/F/aspnetmaster/api/v2/

In order for this to be easy to get going, I have included them in the “lib” folder. The “project.json” files in the “wrap” folder point to these local assemblies.

 Unit Testing

At the time of releasing, the solution passes all unit tests.  Make sure they run for you too if you are contributing to the repository.

 Contribution, Issues and Discussions

 I would love it if you make a fork and create a pull request. Let’s keep all discussions and issues in GitHub. Anything that you need to be updated or fixed – let us know and if time allows for it we will look into it. Feel free to follow the patterns and contribute.

 We will keep a close eye on updates to ASP.NET Identity 3, especially around RC2 and a final version.

 

 

Authorizing Office 365 SharePoint Apps to read Azure AD data

I've been using the Azure AD Graph API in SharePoint/Office Apps for some time now and the changing releases of the different Microsoft products definitely makes it very confusing for newcomers. The documentation has a long way to go, it is quite tricky with the very few examples that use old API's. I hear that people find it frustrating to get going with the Graph API.

This blog post describes how you can make use of Azure AD in Office/SharePoint Apps, what API's to use and how to authenticate your App. I have been using a technique for a while now and it is still not widely popular, most likely because it is not documented anywhere. I have been presenting on it for a while now:

  • Microsoft InTouch conference 2014
  • EUSPC 2014 in Barcelona
  • SharePoint Days 2014 in Slovenia
  • JSNext 2014 in Bulgaria

Scenarios

  • You are building a SharePoint App that needs to read user data that does not exist in the User Profiles in SharePoint Online
  • You need to get a list of members in a group in Azure Active Directory in a provider-hosted SharePoint App that will run in Office 365
  • You need to reach to other directory objects in Azure AD like Roles, Conference Rooms, Computers, etc.
  • You DON'T have an Azure subscription (you don't need one!)

Background

The first key point to understand: every Office 365 tenant has an Azure Active Directory instance in the background. This was never well-known and it took some time in the industry before the mass population got a grasp of that fact. DirSync helped, but terminology definitely changed, and so did the Azure landscape.

One of first and best posts out there that highlighted this was by fellow MVP Chris O'Brien: http://www.sharepointnutsandbolts.com/2014/04/using-azure-instance-behind-your-office-365-tenant.html His does a great job to show you how you can fiddle with your Office 365 users with a trial Azure subscription.

The second key point: SharePoint Apps get "registered" as Applications (Service Principals) in Azure AD. I will show you how to see that further below.

And the third point: You *don't need* an Azure subscription to work with Azure AD, you can use PowerShell. You will miss out on the awesome web portal, but you can still do your job. Many blog posts show how to do it through the Azure portal, but most don't have an Azure subscription.

Azure Active Directory – a few words

For those not so familiar with Azure AD, it is just a directory in the cloud J There are tons of examples of how Azure AD delivers significant value, but here we focus on what is different from Active Directory on-premises that is relevant to Apps.

Instead of using LDAP to communicate with AD, when using Azure AD we use HTTP-based authentication standards and packet flow: SAML-P, OAuth 2.0, WS-Federation. That's all you need to know for now.

Again, all Office 365 (Multi-tenant) tenants have an instance of Azure AD in the background, so if you are doing anything with Office 365 development, you will eventually come across this.

 

The Graph API

So no LDAP, no DirectorySearcher, no old ways to interrogate the directory. The Azure AD team has built what is called the Graph API.

The terminology is confusing, but if you've been in the SharePoint/Office world that has always been the case. I am sometimes confused myself:

This blog post is specifically about the Azure AD Graph API and how you can use it in SharePoint Apps.

So, why would you care about all this?

As we're moving from On-premises to more and more development in Office 365, you will eventually hit the need to get information from Active Directory that is not in neither the User Profiles, nor attainable through the Office Graph GQL search interface. You will need to do stuff in AD that you just can't do through other API's, for example getting a user's country or Office 365 license information through the User Profiles CSOM API.

Steps to give SharePoint Apps permission to Azure AD

So now with the background out of the way, let's dig into it. As I mentioned previously, you don't need an Azure subscription to read Azure Active Directory data – your Office 365 tenant gives you everything you need.

Our goals:

  • Register a SharePoint App with your tenant -> get a ClientId and ClientSecret
  • Give permissions to the App to call Active Directory using the Graph API
  • Show some code

Registering a SharePoint App with a tenant

I use this technique with our clients when we develop something that is a one-off case, and mainly when we build console applications or windows services that do periodic work on SharePoint Online tenants. I use AppRegNew.aspx and you could read more about it here: https://msdn.microsoft.com/en-us/library/office/jj687469(v=office.15).aspx

You can also find more samples where I use this technique in OfficeDev Patterns & Practices: Core.UserProfiles.Sync Governance.EnforceContentTypeRetention and a few others

  1. Open https://[tenantname].sharepoint.com/_layouts/15/appregnew.aspx
  2. Generate your ClientId and ClientSecret, and fill in the other fields:

If you are just building a console app with no user interaction, the AppDomain & Redirect URI could be just "localhost" & "https://localhost".

Confirm and copy your ClientId and ClientSecret. You could also use AppInv.aspx to give your app permissions to SharePoint data. See one of the OfficeDev PnP samples for more info on that.

Give your App access to Active Directory

This is where the real fun begins.

After you used AppRegNew.aspx, you might wonder where that App configuration goes… Let's have a look.

  1. To use PowerShell with Azure Active Directory you need to get the Azure AD modules: (also described here: Core.UserProfiles.Sync )

http://msdn.microsoft.com/en-us/library/azure/jj151815.aspx is the official MSDN page.

Open the Windows Azure Active Directory PowerShell module (or you can just import the modules):

  1. Connect to your tenant:

Connect-SPOService -Url https://onebitsoftware-admin.sharepoint.com -Credential admin@onebitsoftware.onmicrosoft.com

  1. Purely for academic purposes, poke around:

To prove that SharePoint Apps get registered as Azure Active Directory service principals, run this command:

## Set the app Client Id, aka AppPrincipalId, in a variable

$appId = "06277b15-fc38-4df8-bf93-a76c9f9e5dc2"

 

## get the App Service Principal

Get-MsolServicePrincipal -AppPrincipalId $appId

 

You will get this:

Notice "AppPrincipalId" -> this is the ClientId, there is just a huge element of bad and misaligned terminology.

But the point is made, AppRegNew.aspx registers a SharePoint App as an Azure AD service principal. The Service Principal Names are taken from the AppDomain property and the client Id. The Display Name is what you put in the AppRegNew.aspx form.

NOTE: SharePoint Apps will not appear in the Azure web portal, there are reasons for this and it is normal. See this: Application Objects and Service Principal Objects https://msdn.microsoft.com/en-us/library/azure/dn132633.aspx

  1. Give your App access

Again, for academic purposes, run Get-MsolRole:

This is a list of all roles in AD that you could assign. In our case the "Directory Readers" role is what we need. So let's give that role to our App:

## Set the app Client Id, aka AppPrincipalId, in a variable

$appId = "06277b15-fc38-4df8-bf93-a76c9f9e5dc2"

 

## get the App Service Principal

Get-MsolServicePrincipal -AppPrincipalId $appId

 

## Get the Directory Readers Role

$directoryReaderRole = Get-MsolRole -RoleName "Directory Readers" ##get the role you want to set

 

##Give the app the Directory Reader role

Add-MsolRoleMember -RoleMemberType ServicePrincipal -RoleObjectId $directoryReaderRole.ObjectId -RoleMemberObjectId $appPrincipal.ObjectId

 

You are DONE!

To validate, run this:

##Confirm that the role has our app

Get-MsolRoleMember -RoleObjectId $directoryReaderRole.ObjectId

 

And you will see:

Notice Yammer?? That's how Yammer gets data from Azure AD J This gives you significant info on how things work in AD.

Test access and get going with some code


So, now you need to test, then write the actual code for the SharePoint App.

First, some reading:

http://blogs.msdn.com/b/aadgraphteam/archive/2014/12/12/announcing-the-new-version-of-graph-api-api-version-1-5.aspx

https://msdn.microsoft.com/en-us/library/azure/dn835125.aspx

To test your app authentication, use the Graph Explorer: https://graphexplorer.cloudapp.net/

Type in your tenant UPN followed by /Users to get all users:

When you click Get you will get a login prompt:

Principal Id is the same as "ClientId" and "AppPrincipalId" (bad terms!)

"Symmetric Key" is "ClientSecret".

Click log in and you will get your results J Beware of caching issues!!

Add the Graph Client Library to a project

Now that your authentication is set up, grab the Graph Client Library through Nuget:

https://www.nuget.org/packages/Microsoft.Azure.ActiveDirectory.GraphClient/

That is pretty much all you need! You should keep your assemblies fresh, however beware of the changes, "GraphClient" & "GraphConnection" are old API's, "ActiveDirectoryClient" is the object in 2.0.

Code samples

There's not a hell of a lot of code samples out there, but there are a few to help you get going. I put together an update to the OfficeDev PnP sample "AzureAd.GroupMembership" so check it out:

Core.UserProfiles.Sync - https://github.com/OfficeDev/PnP/tree/dev/Solutions/Core.UserProfiles.Sync - this example gets the Country from Azure AD and syncs it to SPO User Profiles, where that field is unavailable.

(no need for me to paste the code here)

 

The Azure AD Graph Team have good samples too:

http://blogs.msdn.com/b/aadgraphteam/archive/2014/12/12/announcing-azure-ad-graph-api-client-library-2-0.aspx

https://github.com/AzureADSamples/ConsoleApp-GraphAPI-DotNet

https://github.com/AzureADSamples/webApp-GraphAPI-DotNet

That should be enough to get you going, good luck J Please feel free to reach out to me and ask questions, I would be glad to help. You might find me junking in the Yammer OfficeDev Patterns & Practices group.

Debugging and troubleshooting SharePoint – Part 1

A friend of mine asked me a very cool question: "how does an MCM troubleshoot and debug SharePoint?" Well, as simple as the question is, I prepared a big set of tips that I believe are extremely unpopular in the SP development space, yet extremely powerful if used in the right way.

 

I use these techniques in my everyday SP life both in development and when we do troubleshooting. This is a multi-part set of posts, where I'm going to start with some easy stuff, then increase the complexity:

 

Debugging and troubleshooting SharePoint

Part 1: Using a console listener during deployment (this post)

Part 2: Following the order of feature installation and activation

Part 3: Don't forget about the Developer Dashboard!

Part 4: ULS troubleshooting tips

Part 5: Debugging SharePoint JavaScript

Part 6: Turn on Fusion logging to troubleshoot assembly loading/binding information

Part 7: Profiling SharePoint with the ASP.NET Profiler

Part 8: Collecting SharePoint intelligence with IntelliTrace

Part 9: Debugging SharePoint code execution with decompilers and reflection tools

Part 10: Debugging SharePoint memory dumps and live execution with WinDbg

 

 

Part 1) Use the Console Listener to send messages to PowerShell while deploying WSP's:

 

This part is easy, but sometimes very helpful. I have created an awesome WSP that uses TraceListener to send output messages. It is a convenient way to get output to the console when deploying with PowerShell.

 

Some quick code:

public static void WriteToLog(string message)

{

//Quick lame check to ensure our listener is not there

bool containsListener = false;

foreach (TraceListener item in Debug.Listeners)

{

if (item.Name == CustomConsoleListener)

containsListener = true;

}

 

//Add listener if it doesn't exist

if (!containsListener)

{

TextWriterTraceListener writer = new TextWriterTraceListener(System.Console.Out, CustomConsoleListener); //type console and name

Debug.Listeners.Add(writer); //register the Console listener

}

 

//send message

Debug.WriteLine(message + " " + Version); //Send message to the console

}

In my feature I have:

public override void FeatureActivated(SPFeatureReceiverProperties properties)

{

ConsoleLogger.WriteToLog(DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss.fff tt") +

" WebApplicationFeature2 FeatureActivated Event" + properties.Feature.Parent.ToString());

}

 

When deploying with PowerShell, you will see the following output:

 

(I have crossed out the name of my web application as it is "sensitive", and I have many features.)

 

Note, the SharePoint Timer Process responsible for deployment of WSP's without the –Local switch doesn't have a console.

 

The above helps when figuring out deployment issues predominantly during development when you are trying to get things right.

 

Another very interesting point regarding this is the "Activate on Default" setting:

 

Activate on Default: It is only relevant to Farm and WebApplication scoped features. The deployment framework will automatically activate the feature if this is set to True and the scope is either Farm or Web Application. I blogged about it ages ago here: "Activate on Default" confusion and features scoped at Web Application level

HOWEVER, there is a slight gap here… if the solution is a Sandbox Solution, this setting will also trigger on features at the Site scope. Ignore the documentation, it doesn't tell you this.

 

Always Force Install: this setting will get rid of the annoying message that tells you the feature is already activated at the scope. While it is very annoying during development, in a real-life production environment it makes a lot of sense. It reminds us that re-activating the feature will apply all feature elements and execute feature receiver code. Forcing the activating will suppress that message for features at any scope level.

 

Auto Activate in Central Admin: This setting name actually gets it right for once, it will automatically activate the feature at Web, Site or Web Application level on Central Administration.

 

Until next time, where I show how the feature activation order works.

 

 

 

Recompiling your own version of the SharePoint code to suit your needs

Ever been pissed off at the SharePoint code? Banging your head against the wall, trying to figure out why something is not working for you, you're looking at it with a reflection tool and just want to see what would happen if you change a single line of code?

You don't have the SharePoint source code, but you still want to fiddle with it and compile your own build? You might have never thought that is possible, but here in this post I will show you how!

This is by far extremely awesome and some seriously fun shit, so enjoy!

(Disclaimer: don't do this, seriously. Just learn from it. I am sure that reverse engineering is written to be forbidden somewhere. And don't do this anywhere near a production server.)

STEP 1) Get the Reflexil plugin, either in Reflector or Telerik JustDecompile. It is called "Assembly Editor" and is available as a JustDecompile Plugin. Ever since Red Gate basterdised Reflector I prefer Telerik JustDecompile, it is free and built in Sofia, where I live and where OneBit Software is located.

Once you get all the components in there, load your tool and the assembly that you want to fiddle with.

In my example I modify Microsoft.SharePoint.ApplicationPages.Administration.dll, to make the CA UI show that I have a custom build, but you could easily do this with Microsoft.SharePoint.dll or any other assembly.

STEP 2) Browse through the assembly and find the code you want to modify. If you are tweaking a property, you need to specifically select the getter or setter. The UI will look like below, with many tabs in the Reflexil UI:

Right-click and either choose to edit the instruction, or "Replace all with code" for the fun stuff.

STEP 3) You will end up in an interface looking like the one below. On the left you will see generated code, on the right you will see instruction information. In my example, I replaced return default(string); with return "Radi's Custom SP Build!";

Make sure the Compiler version is the one relevant for the assembly, in my case v3.5, and hit Compile. You will get standard compiler errors if you have screwed something up. Otherwise if successful, the Instructions on the right will change as per your modification. That stuff is IL, you might already be familiar.

STEP 4) Go ahead and save your modified assembly. It will prompt you to save it with "Patched" in the filename:

STEP 5) After you save it, Reflexil/Telerik JustDecompiler will tell you some very important stuff about the Strong Name of the assembly. This step is key to get this to work and there's deep theory about assembly signing coming to play.

Assemblies are usually signed with a key so that they don't get tampered with in the way I'm doing it. Unless you have the key you can't modify it and resign it. This is something that Visual Studio does when it builds an assembly.

You can either remove the Strong Name, or register the assembly for verification skipping. This is something you could do with the sn.exe tool, or just through the interface below:

"Register it for verification sipping" requires that "sn.exe" is in the path variable so the tool can call it. It will basically execute:

sn -Vr yourAssembly.dll

I had to add "C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools\x64" to my Environment PATH variable and restart JustDecompiler. You might want to do this before you edit assemblies so you don't have to do it again. This is what you will see if sn.exe is not found:

 

STEP 6) What you should see next is the patched assembly, but the most important part is the PublicKeyToken, it should not be null:

 

STEP 7) The last step, rename the "Patched" DLL to its original name, then do an IISRESET.

 

And here she is, the most beautiful SharePoint release ever:

Please comment if you like this post!