Tuesday, December 6, 2016

No way to host server side code in container

When "SharePoint Framework" was released, I was pretty sure that, sooner or later, Microsoft would host server side code in containers (http://fangdahai.blogspot.com.au/2016/05/the-future-of-sharepoint-development.html)

After a few days of testing the container feature on Windows Server 2016, I realised that it was never going to happen :-(

The installation media of SQL Server Express 2016 with SP1 is around 421 MB (64 bit). After put it into windows container, how much disk space it takes? 10 GB!

The post Windows Containers Compared: WinDocks vs. Microsoft is correct. There is something wrong with "Windows Container" by design. To me, "Windows Container" is more like "Windows Nano Server" virtual machine.

Friday, November 25, 2016

"This item is no longer available" when trying to approve master page changes

After some minor change of a master page in SharePoint designer, I checked it in as a major version. SharePoint designer then opened the library "Master Page Gallery" ( /_catalogs/masterpage/Forms/my-sub.aspx ).

I can see the two changed master page files ( .html and .master ) in the "My submissions" list view. However, when trying to open the context menu to approve it, I got the error message "This item is no longer available".

I logged on as SharePoint farm administrator, so it should not be caused by permission issue.

Google leads me to this one, but it doesn't help.

In the end, I changed the versioning settings of this library, which fixed the problem.

Then I changed the settings back.

This is the first time I got this issue in the past 9 years. I guess it's caused by a minor bug. As alternative solution, it's good enough.

The environment is SharePoint 2016 with CU 201611.

Wednesday, November 23, 2016

How to make Chrome support SSO, and enable CORS

Recently I migrated some SharePoint web parts from C# to JavaScript + HTML

Everything works well in IE 11 after enabling CORS.

But, when test it in Chrome 54, I got the error message below, and it constantly prompt for user name and password..

ERR_INVALID_HANDLE: "This site can’t be reached"

IIS log says it's requested by anonymous user.

After days of struggling, it turns out not as easy as it looks like.  We need to do the following steps.

1. IE -> internet options -> security -> Local Intranet zone

Add SharePoint Server and the Web App Server to "Local Intranet zone". So IE and Chrome will try to use the current windows user credential to log on web server.

This enables NTLM authentication on SharePoint and Web App Server.

Reference: https://sysadminspot.com/windows/google-chrome-and-ntlm-auto-logon-using-windows-authentication/

2. Configure Delegated Security in Google Chrome

Need to add server names as below to registry table on client computer.

We can do it through Group Policy.



This enables NTLM authentication and Kerberos on SharePoint and Web App Server.

Reference: https://specopssoft.com/configuring-chrome-and-firefox-for-windows-integrated-authentication/

3. Configure Kerberos

Set up SPN for both the SharePoint Server and the Web App Server.

Reference: https://support.microsoft.com/en-au/kb/929650

4. Change Startup.cs a bit in Configure() to handle preflight requests

This is for CORS.

Reference: http://stackoverflow.com/questions/38838006/asp-net-mvc-core-cors

5. Enable Anonymous Authentication on Web App Server

This is for CORS.

6. If Kestrel Server is not running, we need to submit "GET" request first.

It cannot be started up by "Preflight Options" request. It seems like a bug.

[update 2016-11-29] 7. To make things easier, add the settings below to the web.config file of Web App Server. 

This helps to enable CORS.

<clear />
<add name="Access-Control-Allow-Origin" value="http://SharePointSiteUrl" />
<add name="Access-Control-Allow-Headers" value="Authorization, X-Requested-With, Content-Type, Origin, Accept, X-Auth-Token" />
<add name="Access-Control-Allow-Methods" value="*" />
<add name="Access-Control-Allow-Credentials" value="true" />
<add name="Access-Control-Max-Age" value="60" />



Test Environment.

Client side: Chrome 54 + JavaScript + JQuery 3.1.1

Server side: SharePoint Server 2016 CU201611 + Content Editor Web Part

Web App Server: IIS 8.5 + Asp.Net Core Web API 2 + C#

JavaScript + JQuery 3.1.1 (based on JSON, in a Content Editor Web Part)

var strUrl = "http://WebService2016dev.DomainName.local/SSO/AppTest1/api/SSOAuthentication";

var JSONObject= {"Key": "db25f36b-fa81-4c8e-9af5-9c8468ce8a79",
   "UserLoginName": "domain\\UserLoginName",
   "ReturnCode": "",
   "ReturnValue": "",
   "ReturnDetailedInfo": "" };
var jsonData = JSON.stringify(JSONObject);

$.support.cors = true;

var strMethodType = 'GET';
var strContentType = 'text/plain';

$.ajax( {
url: strUrl,
type: strMethodType,
contentType: strContentType ,
xhrFields: {
withCredentials: true
data: '',
dataType: "json",
async: false,
crossDomain: true,
success: function( response ) {
console.log("GET success - Data from Server: " + JSON.stringify(response));
error: function( request, textStatus, errorThrown ) {
console.log("GET error - You can not send Cross Domain AJAX requests: textStatus=" + textStatus + ", errorThrown=" + errorThrown);
} );

var strMethodType = 'POST';
var strContentType = 'application/json; charset=utf-8';

$.ajax( {
url: strUrl,
type: strMethodType,
contentType: strContentType ,
xhrFields: {
withCredentials: true
data: jsonData,
dataType: "json",
crossDomain: true,
success: function( response ) {
console.log("POST success - Data from Server: " + JSON.stringify(response));
error: function( request, textStatus, errorThrown ) {
console.log("POST error - You can not send Cross Domain AJAX requests: textStatus=" + textStatus + ", errorThrown=" + errorThrown);
} );

Web App Server (IIS 8.5 + Asp.Net Core Web API 2), main C# code in Startup.cs

app.Use(async (httpContext, next) =>
await next();
if (httpContext.Request.Path.Value.Contains(@"api/") && httpContext.Request.Method == "OPTIONS")
httpContext.Response.StatusCode = StatusCodes.Status204NoContent;


Thursday, November 3, 2016

SharePoint needs lightning fast list and library

After the performance test last time , I realized that SharePoint was still so slow comparing to database system (such as SQL Server). I understand that SharePoint is designed for "people access", not a data repository for other computer system, from the very beginning.

But things are changed.

For current enterprises, SharePoint and commercial database system are the major places to host data. Database is fast, but it's really designed for developers. Normal business users cannot easily create tables, add columns, enter data, and manage the whole database. So, they don't have choice. If there are some data they want to share with other people, they have to put it into SharePoint. What if they want to share 50,000 records? They have to copy them to a SharePoint list. It's painfully slow.

We know why SharePoint is so slow. It provides item-level permission control, versioning, auditing......What if users don't need those features, and just want to share a lot of data with other people or another computer system?

That's what is needed: fast list and library. Users still can create list, add/remove columns, create list view......but no other extra features. It's like a database table in SharePoint, but we still can use CAML query to retrieve data, we still create create list views.

If the list/library is created for people access, it should be based on traditional list templates. If we just need something similar to database table, then we can use "fast list".

"Fast list" is even critical for Office 365: if Microsoft wants to use SharePoint as the major place to host data, performance is extremely important.

By the way, do we still need MS Access then?   :-)

Thursday, October 27, 2016

Making a Link to a Document in SharePoint 2013 Open in client program

When we go to a Document Library list view, we can open the document in client program directly if:

1. In the library settings, the default open behavior is "open in the client application"

2. In Central Admin -> Manage web application -> General Settings -> Browser File Handling -> Permissive

However, if we want to add the document link to a page, then user may get prompt message from IE as below, when clicking that link:

That means the document will be downloaded to local hard drive first, then be opened from there.

What if we want to open the document in the SharePoint library directly?

If "Office Web Apps" ("Office Online Server") is available, we can follow this link to open the document in web browser. Or else, we need the help of JavaScript. Insert a Content Editor Web Part to that page, then add the script below to it.  Done!

" rel="sp_DialogLinkNavigate">Document Link Label

Friday, October 14, 2016

The smart watch everyone needs

There are many different types of smart watch on the market. The question is, do we really need them? Do they really change our life style? How many people need to record their heart beat / blood pressure / location all the time? Do we enjoy playing games on "watch"? Do we really want to use "smart watch" to replace "smart phone"? All current smart watches are developed in wrong direction. Watch is very small, but most vendors want to copy the features from smart phone to it! It's like what Microsoft did before: replicate Windows OS to smart phone. This attempt is doomed to fail from the very beginning. From my point of view, a smart watch everyone needs is a simple one with the features below. No fancy appearance, and it is not going to compete with smart phone. 1. Identity verification. I don't want to carry keys, security passes, membership cards, discount cards, library card, drive license, credit cards, transportation card, cash, etc. And, I even don't need to carry mobile phone everywhere. Smart watch is a perfect device for identity verification: light, handy, not likely to left on car / office / home / hotel, or get stolen. Work with fingerprint scanning, it's also much more secure against hacker's attack. At checkout desk of supermarket, no need to take credit card / cash / smart phone out of pocket any more, just raise your hand, put your finger on the watch, "Beep", done. Do we still need wallet? I doubt it. 2. Receive “Check Code” How many passwords do we need to memorize? How complicated each one need to protect you to resist attacks? With the help of this watch, all online system can turn into "passwordless". Want to log on email system? Please enter your email address, then click "submit" button, wait for a few seconds later, enter the "Check Code" just received on watch, then click "submit" again, done. 3. Receive notification For any important action online, such as payment, no matter it's through credit card or PayPal, or just getting the salary of last week, we can get notification in almost real time.
The same notification can also be sent to specified email account.
So, if anything goes wrong, we can respond in short time. 4. Long lasting battery We don't need to keep the watch running all the time. It should be "wake up" instantly when making payment, and then go to sleep again. So, we may only need to run it for a few minutes a day, which means, it can last for months in one charge! When the battery needs recharge, we will get notification. 5. Remote control / No keyboard. We should not be able to enter any text on the watch. So, all configuration is done through computer or smart phone remotely. That's one of the major differences between Watch and Phone. 6. Tough No dust, no water, no shock, and works well in extreme temperature. 7. Enclosed environment This watch is critical to user's daily life, so, security gets highest priority. To minimize risk, it should not allow any third-party software. 8. Date / Clock Only provide basic information. 9. GPS and Emergency report No map needed, but it's nice to know that you can always get help, anywhere, anytime. 10. Privacy OK, this is the inevitable drawback of this watch. But, as it doesn't collect information more than current mobiles, I assume it's fine. How much I am happy to pay for this kind of watch? $200 is fine. But, I think, Google may be happy to give people for free, as exchange of their personal information.

Wednesday, October 5, 2016

Without backup/restore, how to change managed path of a site collection?

Based on the answer from Microsoft, backup/restore is the only way to change site collection managed path.

"backup/restore" actually copy the whole site collection to a file, then re-import it into SharePoint farm. This approach works well. But, instead of external file, we can also use a temporary database to hold the site collection data. Comparing to "backup/restore", it's much faster.

Below is the PowerShell script.

Mount-SPContentDatabase -AssignNewDatabaseId -Name SP_Content_Tmp -DatabaseServer $DatabaseServer -WebApplication $WebAppUrl

Copy-SPSite -Identity $SiteUrlSource -DestinationDatabase SP_Content_Tmp -TargetUrl $SiteUrlDest

Remove-SPSite -Identity $SiteUrlSource -confirm:$false

Get-SPTimerJob -WebApplication $WebAppUrl job-site-deletion | Start-SPTimerJob

Move-SPSite -Identity $SiteUrlDest -DestinationDatabase $ContentDatabase -Confirm:$false

Get-SPTimerJob -WebApplication $WebAppUrl job-site-deletion | Start-SPTimerJob

Dismount-SPContentDatabase -Identity SP_Content_Tmp -Confirm:$false

[update, 2016-10-19]

Windows Form program to generate PowerShell script: