Friday, January 6, 2017

Provision and automatic update of embedded resources to Resources folder in Sharepoint hive

Automatic provision of embedded resources may be quite annoying unless you know how to do it automatically. Surprisingly I didn’t find articles about this issue so decided to write this post. As you probably know in order to provision own resources (resx) files to Sharepoint Resources folder (e.g. 15/Resources in Sharepoint 2013) we add Resources Sharepoint mapped folder in Visual studio and add resx files there:

By default when we add resx file it is added with Build Action = Content:

If we will create wsp package with such resource file we will see that it will include resx file inside the package:

and manifest.xml will have reference on it:

   1: <?xml version="1.0" encoding="utf-8"?>
   2: <Solution xmlns="http://schemas.microsoft.com/sharepoint/"
   3:     SolutionId="c9c995d9-6cf3-422e-81fc-ffb0f7648610"
   4:     SharePointProductVersion="15.0">
   5:   <Assemblies>
   6:     <Assembly Location="SharePointProject4.dll" DeploymentTarget="GlobalAssemblyCache" />
   7:   </Assemblies>
   8:   <RootFiles>
   9:     <RootFile Location="Resources\Test.resx" />
  10:   </RootFiles>
  11: </Solution>

However we may want to reuse it for using localized strings also from C# code. In order to do that we need to open resx file in Visual Studio designer and set Access Modifier to Internal or Public. After that VS generates .designer.cs file with strongly-typed C# class which we then can use from the code. After that we also need to change Build Action to Embedded Resource:

But if then we will try to create wsp package we will see that resx file is not included to it anymore:

manifest.xml won’t have reference to resource file as well:

   1: <?xml version="1.0" encoding="utf-8"?>
   2: <Solution xmlns="http://schemas.microsoft.com/sharepoint/"
   3:     SolutionId="c9c995d9-6cf3-422e-81fc-ffb0f7648610"
   4:     SharePointProductVersion="15.0">
   5:   <Assemblies>
   6:     <Assembly Location="SharePointProject4.dll" DeploymentTarget="GlobalAssemblyCache" />
   7:   </Assemblies>
   8: </Solution>

And it means that our resx files won’t be automatically updated anymore when we will update wsp solution via Update-SPSolution cmdlet. Does it mean that with ability to use embedded resources from C# we lost automatic updates of resx files? Fortunately no, there is workaround which will allow to have both possibilities.

First thing which we need to do is to add new Empty element to the project:

If you didn’t have features in your project yet VS will create new feature automatically and will add new element there. We don’t need this feature so delete it. If you had already features in the project VS will add new element to one of them – this is also not needed so revert changes in features after new element has been added. Also we won’t need elements.xml file under new element – remove it as well.

Then edit SharePointProjectItem.spdata file under added element (you can see it in Solution explorer when will click Show all files there) and add reference to resx file like this:

   1: <?xml version="1.0" encoding="utf-8"?>
   2: <ProjectItem Type="Microsoft.VisualStudio.SharePoint.GenericElement"
   3:     SupportedTrustLevels="All"
   4:     SupportedDeploymentScopes="Web, Site, WebApplication, Farm, Package"
   5:     xmlns="http://schemas.microsoft.com/VisualStudio/2010/SharePointTools/SharePointProjectItemModel">
   6:   <Files>
   7:     <ProjectItemFile Source="..\Resources\Test.resx" Target="Resources" Type="RootFile" />
   8:   </Files>
   9: </ProjectItem>

Source attribute should contain correct relative path to resx from from SharePointProjectItem.spdata file. And add element to the package in VS designer:

After that if you will publish wsp package you will see that it again contains resx file and reference inside manifest.xml:

   1: <?xml version="1.0" encoding="utf-8"?>
   2: <Solution xmlns="http://schemas.microsoft.com/sharepoint/"
   3:     SolutionId="c9c995d9-6cf3-422e-81fc-ffb0f7648610"
   4:     SharePointProductVersion="15.0">
   5:   <Assemblies>
   6:     <Assembly Location="SharePointProject4.dll" DeploymentTarget="GlobalAssemblyCache" />
   7:   </Assemblies>
   8:   <RootFiles>
   9:     <RootFile Location="Resources\Test.resx" />
  10:   </RootFiles>
  11: </Solution>

Now if you will update wsp via Update-SPSolution your embedded resource files will be updated automatically. The only thing which you need to remember is that if you add new embedded resource to the project you will need to add reference on it to the SharePointProjectItem.spdata. But from my point of view this is not big price for possibility to use resources from the code and have automatic updates for them.

Update 2017-03-07: see also how to provision embedded local UI resources from App_LocalResources folder in this post: Provision and automatic update of embedded resources to App_LocalResources folder under Sharepoint Template/Layouts or Template/ControlTemplates sub folders

No comments:

Post a Comment