by via SharePoint Pro
"Mr Sharepoint" is a blog based on RSS for everything related to sharepoint, it collects its posts from many sites in order to facilitate the updating to the latest technology
Friday, November 4, 2016
4 Email Problems That SharePoint Can Solve Now
by via SharePoint Pro
Microsoft Ignite Interviews with harmon.ie’s Top SharePoint Influencers
At Microsoft Ignite in September, as group of us talked to Laura Rogers (@wonderlaura) about some top of mind topics. It was in the context of the harmon.ie Top SharePoint Influencers festivities, which meant that there were a bunch of people standing around with very strong opinions about pretty much everything.
We answered questions like:
- How are you and your clients keeping pace with the rapid changes in Office 365?
- Are all of the rapid changes in Office 365 creating problems for end users?
- Is the hybrid model that Microsoft provides really helping users transition to Office 365?
- Do you think that Microsoft is going to see real competition from Slack?
- How has your role as a SharePoint expert changed over the last year?
Fortunately, they edited out most of the long-windedness; you just get the nuggets. Thanks to harmon.ie for the recognition and the chance to capture some thoughts via these interviews.
Enjoy!
by Marc D Anderson via Marc D Anderson's Blog
Thursday, November 3, 2016
Microsoft Teams: Is the Who-Bot the KM “Expertise Locator” We’ve Needed for Years?
By far the coolest thing I saw in the launch of Microsoft Teams yesterday was the Who-Bot.
.@Microsoft Teams has a bot called WhoBot that acts as an expertise locator. That's YUGE! Classic KM problem – solved? Still need good data. http://pic.twitter.com/l0VmZDEBj1
— Marc D Anderson (@sympmarc) November 2, 2016
It seems to address the age-old knowledge management question “Who knows about…”, which has for years been talked about as either “Find the Expert” or “Expertise Locator”. In some ways, it’s been one of the holy grails of knowledge management.
Every organization has people in with with expertise which is unknown. A classic example was one I ran across at a client back in the mid-1990s. Yes, we’ve been talking about this for over two decades!
In the example (which is real, as best I can remember the details), there was a PhD scientist with extremely specific and strong skills in bovine biology. That was his job, and he was damned good at it. It also so happened that in a previous part of his career, he had been an explosives expert. Also very top notch, and of course for good.
At one point at the company, our PhD friend saw that his company had launched a product which was made of materials he knew extremely well from his explosives work. But the product wasn’t using those materials efficiently, so the margins were pretty bad.
No one knew about his off-kilter expertise, but it would have accelerated the product development and led to a better product.
Had there been a Who-Bot or expertise locator, when they started the project to develop the product, they could have asked “Who knows about explosives?” or “Who knows about using chemical xyz?” Because the PhD fellow was proud of his prior achievements, those facts would have been in his profile, and they would have immediately gotten a hit. Money saved, productivity gained.
We started using Microsoft Teams yesterday like many others. I really wanted to see what the Who-Bot looked like (even at Sympraxis with two people, we can test this stuff), but I couldn’t find it anywhere.
I asked the T-Bot – which is pre-loaded in Teams, “How do I add bots?'”
T-Bot suggested I head over to the bot gallery to look at my options, but I couldn’t find Who-Bot over there, either. T-Bot is really cool, though, and a great example of “bot-based help”. That’s a wave of the future, too.
I pinged a few contacts about how to enable Who-Bot, but so far no joy. I’ll update this post when I figure it out.
.@Microsoft Teams looks very promising, but good user data is key. Check out @HyperFish to improve the value of your AD user data.
— Marc D Anderson (@sympmarc) November 3, 2016
Now, the flip side of this is that Who-Bot is only going to find what it can find. After all this time, we actually have pretty good ways to figure out what people know.
The most obvious one is what we put into out profiles in SharePoint or elsewhere. In other words, without good metadata about each of us, Who-Bot doesn’t have much to work with.
Luckily, we’re working with a great new company to help solve this problem. As I’m quoted on the Hyperfish Web site:
Hyperfish’s product and its Hyperbot (yup, there’s a bot chapter in this story, too) can help your organization essentially crowd-source improvements to your Active Directory data. It’s a fantastic product built by some very smart people. If you’re interested in it, let us know and we can give you a demo. At Sympraxis, we’re really excited to be working with Hyperfish: this is a set of problems that must be solved.
Hyperfish helps with what’s known in the KM world as explicit knowledge about your profile and skills. Explicit knowledge is known because we’ve taken the trouble to collect it, standardize it, vet it, etc. But there is another kind of knowledge known as tacit knowledge. We express our knowledge tacitly by what we work on or what we do or who we know. (KM purists may say I’m being liberal with my definitions here, but that’s the way I roll.)
Guess what? The Office Graph gets us access to some of that tacit knowledge. Based on the documents we author or view, the people we work with, etc., we can start to identify people with the knowledge we need as well.
The new People Card capabilities rolling out in Office 365 now help us to identify people with knowledge we’d never find otherwise. By seeing who is connected to or works around content and other people, we can identify the experts we need.
Since Who-Bot is tied into the Office Graph, I expect that we’ll get very interesting and deep, layered responses to our questions about “Who knows about…” in quite short order.
Now if I could only get the darned the Who-Bot turned on in our Sympraxis tenant!
by Marc D Anderson via Marc D Anderson's Blog
SHAREPOINT COMMUNITY NEWSLETTER - Prepare your Toolbox for SPFx
Hi everyone,
Welcome to this weeks SharePoint Community newsletter!!
I wanted to share with you a noteworthy new whitepaper by John Liu, MVP Office Server and Services, and his colleague Bart Bouwhuis, fellow SharePoint consultant:
Preparing your Toolbox for the SharePoint Framework with Angular, Webpack and Kendo UI
The future of SharePoint development and customization – starting now, by the way – is the SharePoint Framework (SPFx), a client-side based framework that allows JavaScript customizations on top of SharePoint Online/Office 365.
This whitepaper, though, isn't just about SPFx. It is about SharePoint as a platform with AngularJS and WebPack, and having those pieces ready and aligned for SPFx. It is about a stable set of core tools that works well together. It is about a set of tools that runs today on SharePoint 2016, SharePoint 2013 and SharePoint Online. You can already use these, without having to wait for SharePoint Framework's official release.
So download this whitepaper to:
• See a great set of tools in action
• Learn how to build a practical SharePoint business application using modern web technology
• Get excited about the new SharePoint Framework and related web stack technologies
In the words of the authors:
"The time to jump in is always now (or as soon as you can). We present two months of work representing our hardest effort to promote modern web technologies and SharePoint as a platform.
Please download our whitepaper - Preparing Your Toolbox for the SharePoint Framework with Angular, Webpack and Kendo UI, compare it to what you guys use and let us know what you like or love."
Thats all for this week folks, until next week, happy SharePointing!
Thanks
Fraser
by Fraser Beadle via Everyone's Blog Posts - SharePoint Community
Wednesday, November 2, 2016
Executing Direct SQL Queries on SharePoint Content Databases: Is it a good idea???
This article is based on the findings and lessons learnt during one of my recent assignments which included the development of an Analysis Tool which can gather all Vitals out of a SharePoint Farm which can be further leveraged to take decisions during the migration at some later stage.
While deciding the direct execution of SQL Queries on SharePoint Databases, you should consider the following questions and plan accordingly-
What could be the possible repercussions if we execute direct SQL queries on Content Database?
- Reading from the SharePoint databases programmatically, or manually, can cause unexpected locking within Microsoft SQL Server which can adversely affect performance.
- Any read operations against the SharePoint databases that originate from queries, scripts, .dll files (and so on) that are not provided by the Microsoft SharePoint Development Team or by Microsoft SharePoint Support will be considered unsupported if they are identified as a barrier to the resolution of a Microsoft support engagement.
- If unsupported read operations are identified as a barrier to the resolution of support engagement, the database will be considered to be in an unsupported state.
- To return the database to a supported state, all unsupported read activities must stop.
What are unsupported operations on SharePoint Content Databases?
It is clearly unsupported to update, delete, or insert records. The risks are surely far more obvious. Also be aware that any database changes would definitely break the supportability as stated by Microsoft. Examples of such database changes include, but are not limited to the following:
- Adding database triggers
- Adding new indexes or changing existing indexes within tables
- Adding, changing, or deleting any primary or foreign key relationships
- Changing or deleting existing stored procedures
- Calling existing stored procedures directly, except as described in the SharePoint Protocols documentation
- Adding new stored procedures
- Adding, changing, or deleting any data in any table of any of the databases for the products
- Adding, changing, or deleting any columns in any table of any of the databases for the products
- Making any modification to the database schema
- Adding tables to any of the databases for the products
- Changing the database collation
- Running DBCC_CHECKDB WITH REPAIR_ALLOW_DATA_LOSS (However, running DBCC_CHECKDB WITH REPAIR_FAST and REPAIR_REBUILD is supported, as these commands only update the indexes of the associated database.)
- Enabling SQL Server change data capture (CDC)
- Enabling SQL Server transactional replication
- Enabling SQL Server merge replication
What are supported operations on SharePoint Databases?
- Operations that are initiated from the SharePoint administrative user interface
- SharePoint specific tools and utilities that are provided directly by Microsoft (for example, Ststadm.exe)
- Changes that are made programmatically through the SharePoint Object Model and that are in compliance with the SharePoint SDK documentation
What happen if unsupported data modification is discovered?
If an unsupported database modification is discovered during a support call, the customer must perform one of the following procedures at a minimum:
- Perform a database restoration from the last known good backup that did not include the database modifications
- Roll back all the database modifications
What if previous version of the database that does not include the unsupported modifications is unavailable or if the customer cannot roll back the database modifications?
- The customer must recover the data manually.
- The database must be restored to an unmodified state before Microsoft SharePoint Support can provide any data migration assistance.
- If it is determined that a database change is necessary, a support case should be opened to determine whether a product defect exists and should be addressed.
What can be done if still the content database needs to be queried directly for some reason?
Never run the direct SQL queries on Content Database in Production Environment
Take Following steps:
- Restore the Database backup from Production to Development Environment
- Take Database Offline
- Run SQL Queries with [NOLOCK] option
Before running the above steps make sure the database is not in intermediate stage [nothing is checked out] else can get different document count then actual.
Key Takeaways: Based on the facts exposed by Microsoft Documentation on Direct Query Execution on Content Databases the key takeaways are:
- This is completely unsupported by the EULA you agreed to when you installed SharePoint.
- Your queries are not guaranteed to work after applying any patches or service packs to SharePoint since Microsoft could change the database schema anytime.
- Directly querying the database can place extra load on a server and hence performance issues.
- Direct SELECT statements against the database take shared read locks at the default transaction level so your custom queries might cause deadlocks and hence stability issues.
- Your custom queries might lead to incorrect data being retrieved.
by Prashant Bansal via Everyone's Blog Posts - SharePoint Community
Tuesday, November 1, 2016
Azure Storage REST API: Authenticate with C#
In one of my projects where I've been refactoring a traditional .NET project into a .NET Core project, I used the Azure Storage nugets. As of this posting, the current version of the NuGet supports .NET Core which is awesome - but the dependencies doesn't.
Why is this a problem? Well, because if you want to migrate this code to run on .NET core and you rely on the Windows Azure Storage NuGet Package, it will not be possible to run it in .NET Core currently.
That's why I chose to use the Azure Storage REST API instead for all my things - and I haven't regretted a single moment of it (except for trying to figure the auth part out).
The authentication/authorization bits were not really clear. Well, clear as mud perhaps - the documentation is there, but it's quite confusing and lacks any good samples. So with that, I decided to make a sample.
Enjoy this tip-of-the-day post, and feel free to drop me a comment or e-mail.
Authenticate Azure Storage REST requests in C#
Everything I've built is based on information from this page: Authentication for the Azure Storage Services.
Pre-requisites
In order to use this code, there's a few pre-requisites that I'd like to note down:
- You should have an Azure Storage account.
- You should have your Storage Account Key.
- You should have your Storage Account Secret.
- NO need for the Storage Connection string.
- The
Clientobject in my code is a normalnew HttpClient();
Required Headers
As mentioned in the public documentation, there's a few headers that are required as of this posting:
- Date
- Authorization
The rest of the headers are optional, but depending on what operations you want to do, and which service you're targeting, they will differ. This is focused on Table Storage currently, but can be applied to others as well.
Creating the Date Header
This is a required header, and the easiest way to demonstrate how to build it is like this:
var RequestDateString = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture);
if (Client.DefaultRequestHeaders.Contains("x-ms-date"))
Client.DefaultRequestHeaders.Remove("x-ms-date");
Client.DefaultRequestHeaders.Add("x-ms-date", RequestDateString);
If there's already a Date header present, remove it and add it again with the proper value.
Creating the Authorization Header
This is where the tricky part came into play. Seeing it now in retrospective, it's fairly straight forward - but before figuring out in what order, and how to properly encode this header it was a slight struggle.
var StorageAccountName = "YourStorageAccountName";
var StorageKey = "YourStorageAccountKey";
var requestUri = new Uri("YourTableName(PartitionKey='ThePartitionKey',RowKey='TheRowKey')");
if (Client.DefaultRequestHeaders.Contains("Authorization"))
Client.DefaultRequestHeaders.Remove("Authorization");
var canonicalizedStringToBuild = string.Format("{0}\n{1}", RequestDateString, $"/{StorageAccountName}/{requestUri.AbsolutePath.TrimStart('/')}");
string signature;
using (var hmac = new HMACSHA256(Convert.FromBase64String(StorageKey)))
{
byte[] dataToHmac = Encoding.UTF8.GetBytes(canonicalizedStringToBuild);
signature = Convert.ToBase64String(hmac.ComputeHash(dataToHmac));
}
string authorizationHeader = string.Format($"{StorageAccountName}:" + signature);
Client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("SharedKeyLite", authorizationHeader);
As you can see, it's not entirely straight forward. These are the steps and things to consider:
- You first decode the StorageKey from Base64
- You then pass this into the constructor for the HMACSHA256 class
- You then create a byte[] array to get the UTF8 bytes from the canonicalizedStringToBuild (the date + request information)
- You then Base64 encode the hmac.ComputeHash() results
- The result of this, is your signature, in combination with adding the Storage Account Name, so it ends up as a string looking like this format:
StorageAccountName: Signature. - Then you create a new Authorization Header called
Authorizationas you can see in the snippet above, withSharedKeyLiteand your signature added.
I'm going to be honest. This took some time to figure out - but once it was working, it's blazingly fast and I love it.
Accept Header
Since I want the response to be application/json this is exactly what I need to tell the request:
Client.DefaultRequestHeaders.Accept.Clear();
Client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
Request version
I'm specifying which version to use, so if there's new versions coming out I am still targeting the one I know works throughout all of my unit tests and tenants using the code.
This is done using the x-ms-version header.
if (Client.DefaultRequestHeaders.Contains("x-ms-version"))
Client.DefaultRequestHeaders.Remove("x-ms-version");
Client.DefaultRequestHeaders.Add("x-ms-version", "2015-12-11");
DataService Version Headers
Since I'm working with entities, I need to specify the DataServiceVersion headers as such:
if (Client.DefaultRequestHeaders.Contains("DataServiceVersion"))
Client.DefaultRequestHeaders.Remove("DataServiceVersion");
Client.DefaultRequestHeaders.Add("DataServiceVersion", "3.0;NetFx");
if (Client.DefaultRequestHeaders.Contains("MaxDataServiceVersion"))
Client.DefaultRequestHeaders.Remove("MaxDataServiceVersion");
Client.DefaultRequestHeaders.Add("MaxDataServiceVersion", "3.0;NetFx");
If-Match Header
In my specific case I'm doing PUT and DELETE operations sometimes, and when doing that, there's an additional required header you need. The If-Match header.
if (httpMethod == HttpMethod.Delete || httpMethod == HttpMethod.Put)
{
if (Client.DefaultRequestHeaders.Contains("If-Match"))
Client.DefaultRequestHeaders.Remove("If-Match");
// Currently I'm not using optimistic concurrency :-(
Client.DefaultRequestHeaders.Add("If-Match", "*");
}
Known issues: Forbidden: Server failed to authenticate the request.
Before I hit the jackpot on how to format my Authorize header, it generated a lot of different errors. The most common one though, being this:
Status Code: Forbidden, Reason: Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
There was no "easy fix" for this, as it simply meant the header was incorrect for Authorization - but it doesn't state what is incorrect or malformed (which I suppose is good, for security). So after a lot of Fiddler4 magic and experimentation with this, I could resolve the issue and the code you see in this post is the one that is currently (2016-11-01) working as expected throughout all of my projects.
Resources
The snippets here are part of a bigger project of mine, hence I can't easily share the entire source. However, should you be inclined in a full working sample, please drop a comment and if there's enough interest perhaps I'll create a new github project for it.
- Required headers for querying entities: http://ift.tt/1ERsy6m
- Authentication for the Azure Storage Services: http://ift.tt/1DiWTao
by Tobias Zimmergren via Zimmergren's thoughts on tech
Using appsettings.json instead of web.config in .NET Core projects
Recently I was in a discussion with an acquaintance about transforming their projects into .NET Core from their full .NET applications. Some of these apps have a few core helpers, including the very common requirement to read from config files. Most notably it's the web.config or app.config. In this post, I'm simply outlining the minimal steps required to get a grasp on how you can replace those files with the ConfigurationBuilder in .NET Core, and what your new json-based configuration files can look like.
Another tip-of-the-day. Enjoy.
Add settings in a new appsettings.json file
Now, one thing that is important is to specify in your project.json file that the new appsettings.json file should also be copied to the output folder. Remember how you used to do back in the day, when you selected a file and chose "Copy always" etc? Well, now you specify these things in the json config, which makes it very simple and with a great overview of what actually happens when you build.
Add the following section to your project.json, of course with the name of your own file(s) you want to include:
"buildOptions": {
"copyToOutput": {
"includeFiles": [ "appsettings.json" ]
}
}
In my example above, I'm simply copying the appsettings.json file from my project root to the output dir when I compile my project. This enables me to easily find it when running my project.
Contents of appsettings.json
To make it a bit more clear, here's the full content of my very simple appsettings.json file:
{
"StorageConnectionString": "UseDevelopmentStorage=true",
"TestSetting1": "Tobi 1 Kenobi",
"TestSetting2": {
"SubSetting1": "Hello",
"SubSetting2": "World"
}
}
I've added an example of a simple nested configuration here to demonstrate how that works.
Get your config values using ConfigurationBuilder
If you're in a normal class library or Console App, and you don't have the fancy Startup() method everyone is talking about, never fear - the code is here. You don't have to put the config inside of the Startup method to access these configurations; Simply use the ConfigurationBuilder from wherever you want.
Here's what I'm doing in one of my class libraries, which in turn is ran from a console app:
public static IConfiguration GetConfig()
{
var builder = new ConfigurationBuilder()
.SetBasePath(System.AppContext.BaseDirectory)
.AddJsonFile("appsettings.json",
optional: true,
reloadOnChange: true);
return builder.Build();
}
Let's break that down a bit.
SetBasePath
This is where the ConfigurationManager will look for your files. Since I've already specified in my project.json that the appsettings.json file should be copied to the output, I can simply set the base path to the output dir, which brings me to the next one.
System.AppContext.BaseDirectory
This is a way to get the current directory of your executing assembly. If there's other ways to easily get this, which are more up to date with the .NET Core framework, I'd be happy to hear about it in the comments and I would update it. For now, this seems like a valid approach and works in all of my projects.
AddJsonFile
We're going to have to point to our configuration files. In my case I have the appsettings.json file, and this is where you'll let the ConfigurationBuilder know that you want to point to it.
Get properties from config
Now that we have the IConfiguration object (returned from the static method above, for example), it's very easy to work with those values:
Getting the values from your config file is straight forward. Not much different from the traditional ConfigurationManager approach. Simply get the configuration object (as returned from the method I build above in this post) and point to the properties.
Here's a simple test method, making sure that the values come out correctly from this appsettings.json file using the ConfigurationBuilder that we constructed above:
[TestMethod]
public void ConfigurationHelperTests_GetConfigurationFromAppSettingsJson()
{
var settings = ConfigurationHelper.GetConfig();
Assert.IsNotNull(settings);
Assert.AreEqual("UseDevelopmentStorage=true", settings["StorageConnectionString"]);
Assert.AreEqual("Tobi 1 Kenobi", settings["TestSetting1"]);
Assert.AreEqual("Hello", settings["TestSetting2:SubSetting1"]);
Assert.AreEqual("World", settings["TestSetting2:SubSetting2"]);
}
Summary
That's about it for this post. A simple way to check out how your can replace the logic of your old projects that used ConfigurationManager and instead use the new ConfigurationBuilder and point to whatever config file you want.
There's plenty of more ways and gotchas that I haven't had time to document; But upon request I'm putting this out here so there's a starting point.
Check out the section below on resources to read more about how you can work with configuration and settings in your .NET Core projects.
Resources
by Tobias Zimmergren via Zimmergren's thoughts on tech