Tuesday, December 29, 2015

WEBCONFIG.ACCSRV.XML does not have element "configuration/configSections/sectionGroup[@name='SharePoint']" or it is invalid

I recently updated SharePoint 2013 environment using the December 2015 CU packages and ran into an error. There are two (2) SharePoint 2013 servers in the environment. One Web-Front-End SharePoint Server and one Service Application SharePoint Server. On the Service Application Server, the following error message appeared during step 8 of SharePoint Products Configuration Wizard, which I ran after installing all December 2015 CU successfully.

Configuration Failed
...
Failed to install the application content files.
An exception of type System.IO.InvalidDataException was thrown. Additional exception information: The web configuration file, C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\config\WEBCONFIG.ACCSRV.XML, does not have element "configuration/configSections/sectionGroup[@name='SharePoint']" or it is invalid.

First I stopped Access Database Service 2010 and Access Services from the Application Service Server and then ran the Config Wizard again. It did not make a difference.

Then I stopped all services except "SharePoint Server Search" on the Application Service Server and ran the Config Wizard. It completed without error only then.

The following are the list of services I stopped on the Application Service Server.
  • Access Database Service 2010
  • Access Services
  • App Management Service
  • Business Data Connectivity Service
  • Central Administration
  • Claims to Windows Token Service
  • Distributed Cache
  • Document Conversions Launcher Service
  • Document Conversions Load Balancer Service
  • Excel Cacluation Services
  • Lotus Notes Connector (was never turned on)
  • Machine Translation Service (was never turned on)
  • Managed Metadata Web Service
  • Microsoft SharePoint Foundation Incoming E-Mail
  • Microsoft SharePoint Foundation Sandboxed Code Service
  • Microsoft SharePoint Foundation Subscription Settings Service
  • Microsoft SharePoint Foundation Web Application
  • Microsoft SharePoint Foundation Workflow Timer Service
  • PerformancePoint Service
  • PowerPoint Conversion Service
  • Search Host Controller Service
  • Search Query and Site Settings Service
  • Secure Store Service
  • User Profile Service
  • User Profile Synchronization Service
  • Visio Graphics Service
  • Word Automation Services
  • Work Management Service

Also, the lesson I learned was that in SharePoint 2013, it would be best to turn on only the absolutely necessary services or service applications and turn off the ones if they are not absolutely necessary for the sake of the best predictable results in patch installation. 

Thursday, October 22, 2015

One-to-one foreign key relationship in Entity Framework

This site seems to have useful contents for those who want to re-visit their knowledge about Entity Framework.

The example on "One-to-One or One-to-Zero Foreign Key Relationship" was especially useful.

Take a look.

Site Url = http://www.EntityFrameworkTutorial.net


Friday, October 16, 2015

Genenrate full Url (absolute Url) using C# in ASP.NET MVC

A quick way to generate full Url (absolute Url) in ASP.NET MVC:

Url.Action("Details", "Product", new { id = p.ProductID}, Request.Url.Scheme)


If without id, simply use null in the parameter.

Url.Action("Details", "Product", null, Request.Url.Scheme)

Wednesday, October 7, 2015

Stop screensaver autolock

A quick VBScript could be useful in keeping computer active without screensaver automatically taking over. For security policies, most companies have automatic screensaver or session lock in place based on user inactivity. For those of us who need to keep the system monitor PC on all the time, this script could be useful. It basically sends escape key stroke once a minute for the duration of time you specify.

Dim shell, minutes, minuteCount
minutes = 300

Set shell = CreateObject("WScript.Shell")
minuteCount = 0
For minuteCount = 0 To minutes
  shell.SendKeys "{ESC}"
  minuteCount = minuteCount + 1
  WScript.Sleep(60000) 
Next

Just don't forget to lock the computer when you step away from the computer.
To stop the script, close "WScript.exe" in Task Manager or logout from Windows.

Sunday, October 4, 2015

Custom Error Page in ASP.NET MVC

Setting up custom error page for 400 (bad request), 401 (unauthorized), 403 (forbidden), 404 (not found), 500 (internal server error) seemed like a web.config task as simple as specifying
    
<system.web>
    <customErrors mode="On" redirectMode="ResponseRedirect"  >
      <error statusCode="400" redirect="~/CustomError/BadRequest"/>
      <error statusCode="401" redirect="~/CustomError/Unauthorized" />
      <error statusCode="404" redirect="~/CustomError/NotFound"  />
      <error statusCode="403" redirect="~/CustomError/Forbidden"/>
      <error statusCode="500" redirect="~/CustomError/InternalServerError"/>
    </customErrors>
</system.web>
However, the above may not allow our custom error pages to handle certain cases.

For example, the default IIS 404 error page, not my custom error page, will handle 404 for url that is not understood by my MVC application's routing rule (i.e., http://localhost/MyApp/a/b/c/d/e/f).

It may be easier to use <httpErrors> under <system.webServer> rather than <customErrors> in <system .web>. The above can be converted to below. Note that we cannot use ~/ in the path attribute. <system.webServer> is IIS-level override for customError handling in this case. So remove the above and try something like the following.

<system.webServer>
  <httpErrors errorMode="Custom" existingResponse="Replace">      
    <remove statusCode="400" />
    <remove statusCode="401" />
    <remove statusCode="403" />
    <remove statusCode="404" />
    <remove statusCode="500" />
    <error statusCode="400" path="/MyApp/CustomError/BadRequest" responseMode="ExecuteURL"/>
    <error statusCode="401" path="/MyApp/CustomError/Unauthorized" responseMode="ExecuteURL"/>
    <error statusCode="403" path="/MyApp/CustomError/Forbidden" responseMode="ExecuteURL"/> 
    <error statusCode="404" path="/MyApp/CustomError/NotFound" responseMode="ExecuteURL"/>
    <error statusCode="500" path="/MyApp/CustomError/InternalServerError" responseMode="ExecuteURL"/>
  </httpErrors>
</system.webServer>


Below is the Controller


public class CustomErrorController : Controller
{
 public ActionResult BadRequest()
 {
  Response.StatusCode = 400;
  ViewBag.ErrorCode = "400";
  ViewBag.ErrorTitle = "400 Error - Bad Request";
  ViewBag.ErrorMessage = 
   "The resource you tried to access appears to be incomplete.\n" + 
   "Please check your URL and try again.";
  return View("Error");
 }
 public ActionResult Unauthorized()
 {
  Response.StatusCode = 401;
  ViewBag.ErrorCode = "401";
  ViewBag.ErrorTitle = "401 Error - Unauthorized";
  ViewBag.ErrorMessage = 
   "The resource you tried to access appears to require a user permission.\n" + 
   "Please re-launch the browser and try again.";
  return View("Error");
 }
 public ActionResult Forbidden()
 {
  Response.StatusCode = 403;
  ViewBag.ErrorCode = "403";
  ViewBag.ErrorTitle = "403 Error - Forbidden: Access is denied";
  ViewBag.ErrorMessage = 
   "The resource you tried to access is not allowed. \n" + 
   "Please check your URL and try again.";
  return View("Error");
 }
 public ActionResult NotFound()
 {
  Response.StatusCode = 404;
  ViewBag.ErrorCode = "404";
  ViewBag.ErrorTitle = "404 Error - Resource Not Found";
  ViewBag.ErrorMessage = 
   "The resource you tried to access was not found.\n" + 
   "Please check your URL and try again.";
  return View("Error");
 }
 public ActionResult InternalServerError()
 {
  Response.StatusCode = 500;
  ViewBag.ErrorCode = "500";
  ViewBag.ErrorTitle = "500 Error - Internal Server Error";
  ViewBag.ErrorMessage = 
   "An error occurred while system tried to process your request.\n" + 
   "Try again, and if problem persists contact system administrator.";
  return View("Error");
 }
}


And the View

@{
    ViewBag.Title = ViewBag.Title;
}

<div style="text-align: center;">
    <div style="font-size: 10em; color:#ccc; font-weight: bold; ">
        @ViewBag.ErrorCode
    </div>

    <h2>
        @ViewBag.ErrorTitle
    </h2>

    <h3 style="white-space: pre-wrap; word-wrap: break-word;">@ViewBag.ErrorMessage</h3>

    <h4>
        <a href="javascript:void(0);" onclick="javascript: history.go(-1);">Back</a>
    </h4>
</div>


And this is the custom 404 page.


Friday, October 2, 2015

Format <td> to handle linefeed and wrap long text in a table

When a table cell needs to properly display texts with linefeed and really long text with no whitespace (i.e., long URL), try the following styles.
<table style="table-layout: fixed">
  <tbody>
    <tr>
      <td>Some Links</td>
      <td style="white-space: pre-wrap; word-wrap: break-word">
        ...
      </td>
    </tr>
  </tbody>
</table>


Below is a problematic example of table cell display. The long URL text, which has no whitespace character stretches the table's width beyond the specified table width of 400px.
<table style="width: 400px; border: 1px solid white; color: white">
  <tbody>
    <tr>
      <td style="width: 100px; border: 1px solid white; vertical-align: top; ">Some Links</td>
      <td style="border: 1px solid white;" >Link Example: 
        https://www.google.com/maps/@33.7338729,-117.8530829,3a,75y,304h,90t/data=!3m7!1e1!3m5!1suAg9o6LKzX3</td">
    </tr>
  </tbody>
</table>
Some Links Link Example: https://www.google.com/maps/@33.7338729,-117.8530829,3a,75y,304h,90t/data=!3m7!1e1!3m5!1suAg9o6LKzX3



Below is better way to display the content with proper line-feed in order to keep the specified table width of 400px;
<table style="width: 400px; border: 1px solid white; color: white; table-layout: fixed;">
  <tbody>
    <tr>
      <td style="width: 100px; border: 1px solid white; vertical-align: top; ">Some Links</td>
        <td style="border: 1px solid white; 
          white-space: pre-wrap; word-wrap: break-word;" >Link Example:
https://www.google.com/maps/@33.7338729,-117.8530829,3a,75y,304h,90t/data=!3m7!1e1!3m5!1suAg9o6LKzX3</td>
    </tr>
  </tbody>
</table>

Some Links Link Example: https://www.google.com/maps/@33.7338729,-117.8530829,3a,75y,304h,90t/data=!3m7!1e1!3m5!1suAg9o6LKzX3



Monday, September 21, 2015

Set up local email server

Quick way to set up a local email server for development purpose:


  1. Download and Install hMailServer.
  2. After installation, create a test domain, "mail.local".
  3. Run notepad.exe as local admin. 
  4. Open "C:\Windows\System32\Drivers\Etc\host" file.
  5. Add new entry 127.0.0.1  mail.local. Save and close notepad.exe.
  6. Test #5 by pinging mail.local.
  7. In hMailServer console, create a new account admin@mail.local with password under the domain, "mail.local".
  8. Go to Settings --> Protocols --> SMTP.
    Click "Delivery of e-mail" tab. Enter 0 for "Number of retries".
  9. Go to Settings --> Advanced.
    Enter mail.local as the default domain.
  10. Go to Settings --> Advanced --> AutoBan.
    Disable AutoBan.
  11. Go to Settings --> Advanced --> IP Ranges.
    Remove "Internet" and keep "My Computer (127.0.0.1 ~ 127.0.0.1)".
  12. Download and Install Mozilla Thunderbird.
  13. Set up existing account with name = "admin", email = "admin@mail.local" and password from #7.
  14. Test the local email server by sending emails.
  15. Sometimes, the default SMTP port 25 is blocked even to the local PC itself due to network policy. You can change the SMTP port to something else, i.e., 125 at
    Settings --> Advanced --> TCP/IP Ports ---> 0.0.0.0 / 25 / SMTP.
    Change the TCP/IP Port to another available port here.
  16. In order to disable SMTP authentication to avoid SMTP 530 error (authentication is required), go to Settings --> Advanced --> IP Ranges --> Internet --> Require SMTP Authentication. Uncheck "Local to local e-mail addresses", "Local to external e-mail addresses", and "External to local e-mail addresses". Leave check on "External to external e-mail addresses".

Wednesday, September 16, 2015

Saturday, September 12, 2015

SharePoint 2013 + Windows Server 2012 R2 Pre-Requisite Install (Part 2)

When running Setup.exe from SharePoint 2013 install media, we would experience the feared "Prerequisite Missing error message" like below.


There are 10 files to download and install with some care to pass this check successfully. In fact, it is a little bit tricky to perform this pre-requisite installation successfully the first time.


  1. On the SharePoint server, create a folder, "C:\pre".
  2. Download the 10 files below and save them to "C:\pre" folder.
    1. Windows Management Framework 3.0
      http://www.microsoft.com/en-us/download/details.aspx?id=34595
    2. SQL Server 2008 R2 SP1 Native Client
      http://download.microsoft.com/download/9/1/3/9138773A-505D-43E2-AC08-9A77E1E0490B/1033/x64/sqlncli.msi
    3. Microsoft WCF Data Serivces 5.0
      http://download.microsoft.com/download/8/F/9/8F93DBBD-896B-4760-AC81-646F61363A6D/WcfDataServices.exe
    4. Microsoft WCF Data Services 5.6 (To avoid overwrite, rename this download to WcfDataServices56.exe)
      http://download.microsoft.com/download/1/C/A/1CAA41C7-88B9-42D6-9E11-3C655656DAB1/WcfDataServices.exe
    5. Microsoft Information Protection and Control Client
      http://download.microsoft.com/download/9/1/D/91DA8796-BE1D-46AF-8489-663AB7811517/setup_msipc_x64.msi
    6. Microsoft Sync Framework Runtime version 1.0 SP1 (64-bit)
      http://download.microsoft.com/download/E/0/0/E0060D8F-2354-4871-9596-DC78538799CC/Synchronization.msi
    7. Windows Identity Extensions
      http://download.microsoft.com/download/0/1/D/01D06854-CA0C-46F1-ADBA-EBF86010DCC6/r2/MicrosoftIdentityExtensions-64.msi
    8. Windows Identity Foundation (KB974405)
      http://download.microsoft.com/download/D/7/2/D72FD747-69B6-40B7-875B-C2B40A6B2BDD/Windows6.1-KB974405-x64.msu 

      Windows Identity Foundation has been integrated into .NET 4.5. No need to install it.
    9. Windows Server AppFabric
      http://download.microsoft.com/download/A/6/7/A678AB47-496B-4907-B3D4-0A2D280A13C0/WindowsServerAppFabricSetup_x64.exe
    10. Windows Server AppFabric Cumulative Update 1 (KB2671763)
      http://download.microsoft.com/download/7/B/5/7B51D8D1-20FD-4BF0-87C7-4714F5A1C313/AppFabric1.1-RTM-KB2671763-x64-ENU.exe
  3. We are supposed to install prerequisite files via "PrerequisiteInstaller.exe" with specific switches for each downloaded file. In my case, this didn't work too well. You can try the following Powershell scripts, but if you have problems, there is a manual way to install the prerequisite files. I'll go over it in #4.

    PowerShell Script to run prerequisite install altogether:.
    $path = "C:\pre"
    
    Start-Process "E:\PrerequisiteInstaller.exe" –ArgumentList "/SQLNCli:$Path\sqlncli.msi /IDFX:$Path\Windows6.1-KB974405-x64.msu /IDFX11:$Path\MicrosoftIdentityExtensions-64.msi /Sync:$Path\Synchronization.msi /AppFabric:$Path\ WindowsServerAppFabricSetup_x64.exe /KB2671763:$Path\AppFabric1.1-RTM-KB2671763-x64-ENU.exe /MSIPCClient:$Path\setup_msipc_x64.msi /WCFDataServices:$Path\WcfDataServices.exe /WCFDataServices56:$Path\WcfDataServices56.exe"
    
    
    Prerequisite Files (Beware of the last one: AppFabric)

  4. It turns out that all prerequisite files can be installed manually via "Shift + Right Click" and "Run as Administrator", except for the two AppFabric install files.

    "WindowsServerAppFabricSetup_x64.exe"
    "AppFabric1.1-RTM-KB2671763-x64-ENU.exe"

    To install AppFabric, make sure to uninstall AppFabric from "Add Remove Programs" window from previous failed attempt if any.  Reboot the server if uninstall was performed and run the following in Command Prompt (in admin mode).
    C:\Pre\WindowsServerAppFabricSetup_x64.exe /i CacheClient,CachingService,CacheAdmin /gac
    
    

    (Basically, the above switches are what the "PrerequisiteInstaller.exe" tried to implement when the setup file was run under PrerequisiteInstaller.exe)
  5. Let it run for a couple of minutes. Check with TaskManager and "Add/Remove Programs" to confirm AppFabric 1.1's installation. Then reboot the server, and then run "AppFabric1.1-RTM-KB2671763-x64-ENU.exe" with "Run as Admin". This should be the end of SharePoint 2013's prerequisite installation, and you  should be able to proceed with the SharePoint 2013 setup.

SharepPoint 2013 + Windows Server 2012 R2 Pre-requisite Install (Part 1)

This will save some time when building a SharePoint 2013 dev envionrment or when setting up SharePoint server in general.
Import-Module ServerManager

Add-WindowsFeature NET-WCF-HTTP-Activation45, NET-WCF-TCP-Activation45, NET-WCF-Pipe-Activation45

Add-WindowsFeature Net-Framework-Features,Web-Server,Web-WebServer,Web-Common-Http,Web-Static-Content,Web-Default-Doc,Web-Dir-Browsing,Web-Http-Errors,Web-App-Dev,Web-Asp-Net,Web-Net-Ext,Web-ISAPI-Ext,WEB-ISAPI-Filter,Web-Health,Web-Http-Logging,Web-Log-Libraries,Web-Request-Monitor,Web-Http-Tracing,Web-Security,Web-Basic-Auth,Web-Windows-Auth,Web-Filtering,Web-Digest-Auth,Web-Performance,Web-Stat-Compression,Web-Dyn-Compression,Web-Mgmt-Tools,Web-Mgmt-Console,Web-Mgmt-Compat,Web-Metabase,Application-Server,AS-Web-Support,AS-TCP-Port-Sharing,AS-WAS-Support,AS-HTTP-Activation,AS-TCP-Activation,AS-Named-Pipes,AS-Net-Framework,WAS,WAS-Process-Model,WAS-NET-Environment,WAS-Config-APIs,Web-Lgcy-Scripting,Windows-Identity-Foundation,Server-Media-Foundation,Xps-Viewer


Note: The third command is a single line. Remove any line-feed / carriage-return before running the script in PowerShell.

Sunday, September 6, 2015

.NET optimization service at very high CPU utilization

On Server 2012 R2, after running Windows Update to install important updates, the CPU utilization of the server could get pegged at 100% due to .NET optimization service (Ngen.exe).

As the name suggests, all installed .NET frameworks are being optimized via re-compiling, which leads to a prolonged period of 100% CPU usage.

Run the following if you want to get this optimization process over with at your command. Run it and come back after a while (10~20 min). When it is done, the server should behave normally.

 Get-ChildItem $env:SystemRoot\Microsoft.net\NGen.exe -recurse | ForEach-Object { & $_ executeQueuedItems }


Basically, the command above lets us to run "Ngen.exe  executeQueuedItems" per each .NET Framework versions manually at the time of our choosing, rather than letting the server finish when it can later, which may cause unexpected slowness in performance.

After optimization is done for each .NET Framework version, when running the command again, you will see confirmation message like below.


Thursday, September 3, 2015

C# quick extension method refresher - Left() and Right() methods

Here's a quick refresher of C#'s extension methods. If you are not familiar with or forgot about extension methods, check out this post at dotnetperls.


using System;
     
public class Program
{
 public static void Main()
 {
  Console.WriteLine("Hello World");
  
  string a = "Hello Orange County";  
  Console.WriteLine("a.Right(6) = " + a.Right(6));
  Console.WriteLine("a.Left(7) = " + a.Left(12));
 }
}

public static class ExtensionMethods
{
 public static string Right(this string original, int numChar)
 {
  string retVal = "";
  if(original != null && numChar >= 0)
  {
   return original.Substring(numChar > original.Length ? 0 : original.Length - numChar); 
  }
  return retVal;
 }
 
 public static string Left(this string original, int numChar)
 {
  string retVal = "";
  if(original != null && numChar >= 0)
  {
   return original.Substring(0, (numChar > original.Length ? original.Length : numChar));
  }
  return retVal;
 }
}

By the way, there is an amazing online C# compiler tool called ".NET Fiddle". It lets you quickly build and test your C# prototype program online, including ASP.NET MVC-based prototypes. Just like the JSFiddle, you can create your own account and start building your own personal code libraries.

Here's a review article about .NET Fiddle.

.Net Fiddle Screenshot