Louis-Charles Gagnon Blog

Microsoft Azure, Office 365 and SharePoint Blog

SharePoint 2013 - Fix Lookup column not linking to a list

Sometimes after deployment or data manipulation, a list is left not connected to a list.

With powershell you can fix individual column to update it's lookup list:

 Function Fix-LookupColumn ($webURL, $listName, $columnName, $lookupListName)
 {
     #Get web, list and column objects
     $web = Get-SPWeb $webURL
     $list = $web.Lists[$listName]
     $column = $list.Fields[$columnName]
     $lookupList = $web.Lists[$lookupListName]
 
     #Change schema XML on the lookup column
     $column.SchemaXml = $column.SchemaXml.Replace($column.LookupWebId.ToString(), $web.ID.ToString())
     $column.SchemaXml = $column.SchemaXml.Replace($column.LookupList.ToString(), $lookupList.ID.ToString())
     $column.Update()
 
     #Write confirmation to console and dispose of web object
     write-host "Column" $column.Title "in list" $list.Title "updated to lookup list" $lookupList.Title "in site" $web.Url
     $web.Dispose()
 }


In order to use this function, simply call the following:

Fix-LookupColumn -webURL <URL> -listName "<List name containing the lookup column>" -columnName "<Lookup column name>" -lookupListName "<List used by the lookup column>"

For example:

Fix-LookupColumn -webURL http://mysite/site -listName "Clients" -columnName "Company" -lookupListName "Company"

SharePoint 2013 - Search service stuck and/or paused for (Paused by System, Index Reset, External Request)

Sometimes the search services gets stuck, following an index reset or a problem with the search component.
When Search service application shows crawl status as “Paused by system” or “External Request”, it can be fixed below:

Display search component status:
$ssa = Get-SPEnterpriseSearchServiceApplication
get-spenterprisesearchstatus -SearchApplication $ssa -Detailed -Text

Resume search component:

(Optional) If not running SharePoint Management:

Add-PSSnappin "Microsoft.SharePoint.PowerShell"

Then:

$ssa = Get-SPEnterpriseSearchServiceApplication
Resume-SPEnterpriseSearchServiceApplication $ssa

Force a index reset (if stuck):

Make sure to reset the Search Host Controller service and timer service before running theses commands.

(Optional) If not running SharePoint Management:

Add-PSSnappin "Microsoft.SharePoint.PowerShell"

Then:

$ssa = Get-SPEnterpriseSearchServiceApplication
$disableAlerts = $true
$ignoreUnreachableServer = $true
$ssa.reset($disableAlerts, $ignoreUnreachableServer)



Send an email with custom recipient ReplyTo and To in SharePoint 2013 via C#

In a recent development for a consulting client. In a custom page, we wanted to send an email with the from a given user and allow the user to reply to email directly to the given user.

We noticed that the reply-to email was the SharePoint Admin Email and not the from displayed in the email.

We tried:

//Set E-mail Header Variables
var messageHeaders = new StringDictionary
{
    {"to", emailTo},                     
    {"from", emailFrom},
    {"replyto", emailFrom},
    {"subject", emailSubject},
    {"content-type", "text/html"}
};

//Send Email by SharePoint
SPUtility.SendEmail(Web, messageHeaders, emailBody);

This did send an email, but the replyto is not overrided.

We used the .NET Send Email method to make this work.

This method retrieves the SharePoint Central Admin smtp server defined in the farm:

var smtpServer = SPContext.Current.Web.Site.WebApplication.OutboundMailServiceInstance.Server.Address;

With that information we can send the email as follow:

var message = new System.Net.Mail.MailMessage();
message.To.Add(emailTo);
message.Subject = emailSubject;
message.From = new System.Net.Mail.MailAddress(emailFrom);
message.Body = emailBody;
message.IsBodyHtml = true;
System.Net.Mail.SmtpClient smtp = new System.Net.Mail.SmtpClient(smtpServer);
smtp.Send(message);



High Performance Cache - Azure Redis Cache (Output Cache and Session State)

One of Azure new preview feature is Azure Redis Cache. This feature allows you to speed up your .net application running Windows Azure. This feature is available since .NET 4.0




The Azure Redis Cache offers High Performance caching with this feature. This features helps your application become more responsive even as user load increases. It leverages the low-latency, high-throughput capabilities of the Redis engine. This separate, distributed cache layer allows your data tier to scale independently for more efficient use of compute resources in your application layer.

How to use it?

  • Login to Azure Portal
  • Add a ressource "Redis Cache"

High Performance - Output Cache

You can configure .net application or website (MVC or other) to use Output Cache via Redis Cache.
In order to do this, you must install the following nuget "RedisOutputCacheProvider" once the dll are loaded to the project, simply modify your web.config to use this feature:

<caching>
  <outputCache defaultProvider="RedisOutputCache">
    <providers>
          <add name="RedisOutputCache"
               type="Microsoft.Web.Redis.RedisOutputCacheProvider"
                port="6380"
                host="MYID.redis.cache.windows.net"
                accessKey="MYACCESSKEYINAZURE"
                ssl="true" />
    </providers>
  </outputCache>
</caching>
In order to use in your .aspx page, simply add the following to the page (at the top)

<%@ OutputCache Duration="60" VaryByParam="*" %>
For more information on this feature, view ASP.NET Output Cache Provider for Azure Redis Cache

High Performance - Session State

You can configure .net application or website (MVC or other) to use Session Cache via Redis Cache.
In order to do this, you must install the following nuget "RedisSessionStateProvider" once the dll are loaded to the project, simply modify your web.config to use this feature:

<sessionState mode="Custom" customProvider="RedisSessionProvider">
 <providers>
         <add name="RedisSessionProvider"
   type="Microsoft.Web.Redis.RedisSessionStateProvider"
   port="6380"
   host="MYHOST.redis.cache.windows.net"
   accessKey="MYAZUREKEY"
   ssl="true" />
      </providers>
</sessionState>
For more information on this feature, see ASP.NET Session State Provider for Azure Redis Cache

Shall you have any questions, need help or other, feel free to contact me lcg@ls2.ca

Microsoft Azure App Service - Set TimeZone for your web application

Azure App Service is a cloud app service that integrates everything you need to quickly and easily build web and mobile apps for any platform or device.



Usually the application would be run on Internet Information Services (IIS) and take the time of the server hosting the application.

In one of my recent migration, we had a web application hosted on IIS that was being migrated to Windows Azure.

This application uses DateTime.Now to display current time and sql time. Once the application was moved to the cloud we notice a timezone offset. The Azure App Service time was based on UTC (GMT 0).

In order to resolve this issue and set the timezone on the app service. You can change the App Settings via the Azure Portal of the web application.

To do so:
  • Log-in to your Azure Portal
  • Click on your App Service
  • Click on Application Settings




Here is the list of possible values for TimeZone (WEBSITE_TIME_ZONE).

  • Value="Morocco Standard Time" For (GMT) Casablanca
  • Value="GMT Standard Time" For (GMT) Greenwich Mean Time : Dublin, Edinburgh, Lisbon, London
  • Value="Greenwich Standard Time" For (GMT) Monrovia, Reykjavik
  • Value="W. Europe Standard Time" For (GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna
  • Value="Central Europe Standard Time" For (GMT+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague
  • Value="Romance Standard Time" For (GMT+01:00) Brussels, Copenhagen, Madrid, Paris
  • Value="Central European Standard Time" For (GMT+01:00) Sarajevo, Skopje, Warsaw, Zagreb
  • Value="W. Central Africa Standard Time" For (GMT+01:00) West Central Africa
  • Value="Jordan Standard Time" For (GMT+02:00) Amman
  • Value="GTB Standard Time" For (GMT+02:00) Athens, Bucharest, Istanbul
  • Value="Middle East Standard Time" For (GMT+02:00) Beirut
  • Value="Egypt Standard Time" For (GMT+02:00) Cairo
  • Value="South Africa Standard Time" For (GMT+02:00) Harare, Pretoria
  • Value="FLE Standard Time" For (GMT+02:00) Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius
  • Value="Israel Standard Time" For (GMT+02:00) Jerusalem
  • Value="E. Europe Standard Time" For (GMT+02:00) Minsk
  • Value="Namibia Standard Time" For (GMT+02:00) Windhoek
  • Value="Arabic Standard Time" For (GMT+03:00) Baghdad
  • Value="Arab Standard Time" For (GMT+03:00) Kuwait, Riyadh
  • Value="Russian Standard Time" For (GMT+03:00) Moscow, St. Petersburg, Volgograd
  • Value="E. Africa Standard Time" For (GMT+03:00) Nairobi
  • Value="Georgian Standard Time" For (GMT+03:00) Tbilisi
  • Value="Iran Standard Time" For (GMT+03:30) Tehran
  • Value="Arabian Standard Time" For (GMT+04:00) Abu Dhabi, Muscat
  • Value="Azerbaijan Standard Time" For (GMT+04:00) Baku
  • Value="Mauritius Standard Time" For (GMT+04:00) Port Louis
  • Value="Caucasus Standard Time" For (GMT+04:00) Yerevan
  • Value="Afghanistan Standard Time" For (GMT+04:30) Kabul
  • Value="Ekaterinburg Standard Time" For (GMT+05:00) Ekaterinburg
  • Value="Pakistan Standard Time" For (GMT+05:00) Islamabad, Karachi
  • Value="West Asia Standard Time" For (GMT+05:00) Tashkent
  • Value="India Standard Time" For (GMT+05:30) Chennai, Kolkata, Mumbai, New Delhi
  • Value="Sri Lanka Standard Time" For (GMT+05:30) Sri Jayawardenepura
  • Value="Nepal Standard Time" For (GMT+05:45) Kathmandu
  • Value="N. Central Asia Standard Time" For (GMT+06:00) Almaty, Novosibirsk
  • Value="Central Asia Standard Time" For (GMT+06:00) Astana, Dhaka
  • Value="Myanmar Standard Time" For (GMT+06:30) Yangon (Rangoon)
  • Value="SE Asia Standard Time" For (GMT+07:00) Bangkok, Hanoi, Jakarta
  • Value="North Asia Standard Time" For (GMT+07:00) Krasnoyarsk
  • Value="China Standard Time" For (GMT+08:00) Beijing, Chongqing, Hong Kong, Urumqi
  • Value="North Asia East Standard Time" For (GMT+08:00) Irkutsk, Ulaan Bataar
  • Value="Singapore Standard Time" For (GMT+08:00) Kuala Lumpur, Singapore
  • Value="W. Australia Standard Time" For (GMT+08:00) Perth
  • Value="Taipei Standard Time" For (GMT+08:00) Taipei
  • Value="Tokyo Standard Time" For (GMT+09:00) Osaka, Sapporo, Tokyo
  • Value="Korea Standard Time" For (GMT+09:00) Seoul
  • Value="Yakutsk Standard Time" For (GMT+09:00) Yakutsk
  • Value="Cen. Australia Standard Time" For (GMT+09:30) Adelaide
  • Value="AUS Central Standard Time" For (GMT+09:30) Darwin
  • Value="E. Australia Standard Time" For (GMT+10:00) Brisbane
  • Value="AUS Eastern Standard Time" For (GMT+10:00) Canberra, Melbourne, Sydney
  • Value="West Pacific Standard Time" For (GMT+10:00) Guam, Port Moresby
  • Value="Tasmania Standard Time" For (GMT+10:00) Hobart
  • Value="Vladivostok Standard Time" For (GMT+10:00) Vladivostok
  • Value="Central Pacific Standard Time" For (GMT+11:00) Magadan, Solomon Is., New Caledonia
  • Value="New Zealand Standard Time" For (GMT+12:00) Auckland, Wellington
  • Value="Fiji Standard Time" For (GMT+12:00) Fiji, Kamchatka, Marshall Is.
  • Value="Tonga Standard Time" For (GMT+13:00) Nuku'alofa
  • Value="Azores Standard Time" For (GMT-01:00) Azores
  • Value="Cape Verde Standard Time" For (GMT-01:00) Cape Verde Is.
  • Value="Mid-Atlantic Standard Time" For (GMT-02:00) Mid-Atlantic
  • Value="E. South America Standard Time" For (GMT-03:00) Brasilia
  • Value="Argentina Standard Time" For (GMT-03:00) Buenos Aires
  • Value="SA Eastern Standard Time" For (GMT-03:00) Georgetown
  • Value="Greenland Standard Time" For (GMT-03:00) Greenland
  • Value="Montevideo Standard Time" For (GMT-03:00) Montevideo
  • Value="Newfoundland Standard Time" For (GMT-03:30) Newfoundland
  • Value="Atlantic Standard Time" For (GMT-04:00) Atlantic Time (Canada)
  • Value="SA Western Standard Time" For (GMT-04:00) La Paz
  • Value="Central Brazilian Standard Time" For (GMT-04:00) Manaus
  • Value="Pacific SA Standard Time" For (GMT-04:00) Santiago
  • Value="Venezuela Standard Time" For (GMT-04:30) Caracas
  • Value="SA Pacific Standard Time" For (GMT-05:00) Bogota, Lima, Quito, Rio Branco
  • Value="Eastern Standard Time" For (GMT-05:00) Eastern Time (US & Canada)
  • Value="US Eastern Standard Time" For (GMT-05:00) Indiana (East)
  • Value="Central America Standard Time" For (GMT-06:00) Central America
  • Value="Central Standard Time" For (GMT-06:00) Central Time (US & Canada)
  • Value="Central Standard Time (Mexico)" For (GMT-06:00) Guadalajara, Mexico City,Monterrey
  • Value="Canada Central Standard Time" For (GMT-06:00) Saskatchewan
  • Value="US Mountain Standard Time" For (GMT-07:00) Arizona
  • Value="Mountain Standard Time (Mexico)" For (GMT-07:00) Chihuahua, La Paz, Mazatlan
  • Value="Mountain Standard Time" For (GMT-07:00) Mountain Time (US & Canada)
  • Value="Pacific Standard Time" For (GMT-08:00) Pacific Time (US & Canada)
  • Value="Pacific Standard Time (Mexico)" For (GMT-08:00) Tijuana, Baja California
  • Value="Alaskan Standard Time" For (GMT-09:00) Alaska
  • Value="Hawaiian Standard Time" For (GMT-10:00) Hawaii
  • Value="Samoa Standard Time" For (GMT-11:00) Midway Island, Samoa
  • Value="Dateline Standard Time" For (GMT-12:00) International Date Line West

Shall you any questions, problems or need help, free fell to contact me lcg@ls2.ca

How to remove "Get Started with your site" from a Team Site - Sharepoint 2013/Online

When you create a new team site on SharePoint 2013 and SharePoint Online, you are presented with a default "welcome" webpart: 


In order to remove this webpart, you may use the client context with the following code:            

Using SharePoint Dll:

          var web = clientContext.Web;
          clientContext.Load(web);

var web = clientContext.Web;

var file = web.GetFileByServerRelativeUrl(web.ServerRelativeUrl + "/SitePages/Home.aspx");

var wpm = file.GetLimitedWebPartManager(PersonalizationScope.Shared);

web.Context.Load(wpm.WebParts, wps => wps.Include(wp => wp.WebPart.Title));

web.Context.ExecuteQueryRetry();


for(var i=0;i<wpm.WebParts.Count;i++)

{

    if (wpm.WebParts[i].WebPart.Title.Equals("Get started with your site"))

    {

        wpm.WebParts[i].DeleteWebPart();

        web.Context.ExecuteQueryRetry();

    }

}




            var web = clientContext.Web;
            clientContext.Load(web);
            web.Context.ExecuteQuery();
            web.DeleteWebPart(web.ServerRelativeUrl + "/SitePages/Home.aspx", "Get started with your site");
            web.Context.ExecuteQuery();

In order to change the default homepage of a team site, here is the code:

            var web = clientContext.Web;
            var rootFolder = web.RootFolder;
            clientContext.Load(web);
            clientContext.Load(rootFolder);
            rootFolder.WelcomePage = "/SitePages/MyHomePage.aspx";
            rootFolder.Update();
            clientContext.ExecuteQuery();