Archive

Archive for the ‘Programming’ Category

SharePoint 2013 Ratings and Internet Explorer 10+

18 March 2014 7 comments

You may have noticed that the star ratings have changed in SharePoint 2013 to utilise the theme of the site, or you may not.  If you haven’t seen them they look like this…

classification

Well most of the time they look like that. But sometimes, when using IE10 or above, they look like this…

classification2

So what is going on here?  After some looking at the code, decompiling, investigating it seems to be an sequencing problem.  Here’s my breakdown.

The RatingFieldControl renders the following HTML:

<span id="RatingsCtrl_ctl00_PageOwnerRviewDateBar_..."></span>
<script type="text/javascript">
    EnsureScript('SP.UI.Ratings.js', typeof(SP.UI.Reputation), function() {
        // Do Stuff
    });
</script>
<div style="display: none;">
    <img id="RatingsLargeStarFilled.png" src="themedfile"></img>
    <!-- other img tags for different parts of the ratings -->
</div>

Well obviously it is is a little more, I’ve distilled it down to the basics.  The first span is filled in by the function included in the script tag.  The last hidden div is used for the script to populate the image files that are required.  And therein lies the problem.

When using fiddler to investigate the problem with rendering in IE10. I could see that the loading sequences when I pressed enter in the address bar vs pressing the refresh button vs using IE8/9 were different.

When the display bug occurs it appears that the EnsureScript, which is part of the Script on Demand libraries, executes immediately since SP.UI.Reputation is already loaded.  This means that when the script goes to find the images it can’t find them because they haven’t been rendered to the page yet.  The simple fix is for Microsoft to change the rendering sequence for their control, as there are private methods involved it isn’t possible for us to just overwrite the render method, and even if we did then our control wouldn’t be the one used in most cases.

There are two solutions I can think of:

1. Calculate the themed source files and specify the images yourself.  This is probably not ideal as a change in the theme will change the files you want to point to, and these can’t be predicted.

2. Re-execute the script after the page has completed rendered to the browser.

I’m going to look at using option 2:

Without going into full details, here is the solution add this JavaScript to the page (I already have jQuery library loaded):

$(function () {
    if (SP.UI.Reputation != null) {
        SP.UI.Reputation.RatingsHelpers.$c(false);
        $('[id^=RatingsCtrl_] ~ script').each(function() { 
            eval($(this).text());
        });
    }
});

How does this solve the problem?

The first line is shorthand for wait for the document.ready event so ensures the script isn’t loaded until after the page has finished loading.

The IF statement detects if the SP.UI.Ratings.js. I could use the EnsureScript here as well, but by checking this way, if the script is still waiting to be loaded then the emitted script above will still be waiting to execute so we won’t need our little hack.

The function line 3 calls the RatingsHelper method responsible for the reading of the img tags for use by the script and thus forces these to be reloaded.

The last block finds, using jQuery selectors, the script blocks associated with the Ratings controls and executes these statements again.  Forcing the display of the star ratings to be updated correctly.

And there you have it, the simplest hack I could find to correct what could easily be done by Microsoft switching a few lines of code around.

Categories: Programming, SharePoint

“Not enough memory” error message when starting Virtual Machines

2 December 2013 Leave a comment

I have a 16GB laptop which when running Windows 8 I was able to start some 10GB+ virtual machines for doing SharePoint development on.  However since upgrading to Windows 8.1 I have been unable to start up these virtual machines.

The cause is in the more aggressive way that Windows 8.1 reserves memory for itself and fortunately Microsoft have some registry settings we can tweak to change this.  For information on these keys refer to http://support.microsoft.com/kb/2911380.  If you want to avoid restarting you machine at least restart the “Hyper-V Virtual Machine Management” service, and schedule a restart for the first convenient opportunity.

Categories: Programming Tags:

TFSVersioning

31 January 2013 Leave a comment

So awhile ago I mentioned automated versioning of components during a TFS Build.  At the time I suggested Chris O’Brien’s approach, which is a good simple approach.  However, if you want something a bit more powerful take a look at TSVersioning.

TFSVersioning is a codeplex project that has heaps of versioning goodness and good documentation to match.

It is really easy to add to build process just following the instructions they have given.

When using this with SharePoint projects the only limitation I found was that you needed to apply the Assembly Version Pattern which obviously you don’t want to do with SharePoint.  This appears to be a limitation in one of the embedded XAML files.

If you want to remove this limitation then just do the following.  Download the source code (I’m using the 1.5.0.0 version.) and open the solution in Visual Studio.

Find the VersionAssemblyInfoFiles.xaml file and open up the designer.

Find the node that task that says “Validate then process Build Definition Values”.  Chagne the “Or” in the condition to an “And” so it reads “String.IsNullOrWhiteSpace(AssemblyVersionPattern) And String.IsNullOrWhiteSpace(AssemblyFileVersionPattern)”.

image

Compile the project and use the DLL instead of the one included in the package.

The other XAML and flows already allow you to specify either the AssemblyFileVersionPattern or AssemblyVersionPattern, just not this flow.

Note:  Version 2 has been released for TFS2012, I do not know if that version has this limitation or not.

Categories: Programming, SharePoint

VS Snippet for Test methods

Ok so you have started doing TDD and you really dislike having to type

   1: [TestMethod]
   2: public void SomeTeast()
   3: {
   4:  // Insert Test code here...
   5: } 

And you really really wish there was a way that you could do this quickly… well there is!!!! It is called a snippet.

To set this up open your "My Documents\Visual Studio 2008\Code Snippets\Visual C#\My Code Snippets" folder, and then create a new Xml file (using whatever hacks you like.  Then paste this xml into it…  (I’ve left it plain to make it easier to copy.)

<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
    <CodeSnippet Format="1.0.0">
        <Header>
            <Title>Test Method</Title>
            <Shortcut>test</Shortcut>
            <Description>Code snippet for basic unit test function</Description>
            <Author>David McEwing</Author>
            <SnippetTypes>
                <SnippetType>Expansion</SnippetType>
            </SnippetTypes>
        </Header>
        <Snippet>
            <Declarations>
                <Literal>
                    <ID>testName</ID>
                    <ToolTip>Name of the Test</ToolTip>
                    <Default>true</Default>
                </Literal>
            </Declarations>
            <Code Language="csharp">
        <![CDATA[
      [TestMethod]
      public void $testName$()
        {
              //Insert code here…
        }]]>
            </Code>
        </Snippet>
    </CodeSnippet>
</CodeSnippets>

Then in Visual studio a new TEST snippet will appear in your list. You use it like this…

Start typing the word "test" you will find that in the drop down a snippet is there for you to use, it looks like this…

When you have selected like above… press tab, twice.

The following will magically appear…

(red squiggles are because I’ve generated these shots using a standard CS file not one setup for tests.)

Type the name for your test and press enter. The cursor will be located ready for you to enter the code for your test. Simple, time saving, and flexible.

Yes Flexible… if you don’t like this snippet or think you can improve, or want variations, just load it, or copy it and then open it, in visual studio. Snippets are a really simple XML file that you can tweak or create new ones to your own content.

NOTE: For Resharper users. Resharper has its own templating system. This method is just for the VS built in way. If you want to use VS’s snippets and not Resharper’s then you will need to set Resharper to use Visual Studio snippets.

Categories: Programming

Using SQL Reporting Services to report on MySQL database

So the other day I was asked to produce a phone book from a MySQL database.  I had already written a SQL Reporting Service (from now on referred to as RS) report in the format that they wanted.  I thought it would be a simple task to just point the RS at the MySQL and be done.  How wrong could I be?  After much searching and a few sneaky tricks I succeeded.   If this doesn’t interest you then stop now… I’m only going to get geeker.  I just want to be able to find this info later.

Problem… SQL Express RS only allows connections to the Local SQL server.  Upgrading SQL isn’t an option because 1. RS only talks to MS SQL servers and 2. Cost.

Solution… Linked Servers!

Linked servers are an advanced SQL feature, that in 10 years of software development have yet to use in a production environment or create a system requiring them.  However they are available in all versions of SQL server from Express all the way through to Data Centre edition.

So here is my solution with thanks to Niklas Henricson and his article on Migrating MySQL to MSSQL.

Step 1: Install MySQL ODBC client on the SQL server.

Any version of the MySQL ODBC Connector should work, but I choose the latest (v5.2) available from http://dev.mysql.com/downloads/connector/

You may want to set up a SYSTEM DSN at this point to check that it is working correctly and you can access the MySQL database, or at least maybe install one of the MySQL clients and make sure you can connect.

Step 2: Cerate a MS SQL Link to the MySQL database.

Open a query window and run the following SQL statement.

EXEC master.dbo.sp_addlinkedserver
@server = N'MYSQL',
@srvproduct=N'MySQL',
@provier=N'MSDASQL',
@provstr=N'DRIVER={MySQL ODBC 5.1 Driver}; SERVER=localhost; DATABASE=tigerdb; USER=root; PASSWORD=hejsan; OPTION=3'
 

Obviously substitute your connection information.  If you aren’t sure what it is then you can always create a .UDL file on your desktop and setup your connection and then open it in notepad to find out.

If you refresh the object explorer you will now see that the Linked server appear.  You can right click on this and set additional properties, like setting up MSSQL to MySQL user mappings.  In my case all I did was set it to always use the same credentials when connecting to MySQL and set them to a read only reporting user I had already created.

Step 3: Querying the database.

This is simple.  Basically you select from an openquery() like this…

SELECT * INTO testMySQL.dbo.shoutbox
FROM openquery(MYSQL, 'SELECT * FROM tigerdb.shoutbox')

But of course the Select statement in the openquery can be quite complex.

Step 4: Optimise

Building a phone list can be quite complex, if you have to match people into family groups and then provide the phone list based on those families.  To make the queries a little simpler I could have built a View within a database on the MSSQL side, but instead I just used a nested select statement.  It appeared to work just as well.

In so doing I found the following:

  1. The query performed faster if I kept the query on the MySQL side to a simple select and then joined on the MSSQL side.
  2. Only return the data you need.  If there are other things in the table that you don’t need, don’t return them.
  3. Return the data in the same sequence, to make matching/sorting quicker on the MSSQL side.

And that is it, the solution is so simple it is brilliant, at least IMHO.

Categories: Programming

Backing up SQL Express Databases

SQL express is very useful for small installations, websites etc.  But more often than not I find it important to Backup the database on a schedule. This feature is supplied in the more advanced versions of SQL server but not in the express edition.

However, thanks to PowerShell it is now possible to provide the same functionality.  This is how I went about it.  Please note that I found most of the supporting functions online and they aren’t really mine.  Just the way I put them together.

First step.  We need to backup the database.

To back up the database you need to execute the following three SQL statements.

   1: BACKUP DATABASE [$DbName] to DISK='$DbFile.BAK' WITH FORMAT, 
   2: NAME='$DbName-Full Database Backup'
   3: GO
   4:  
   5: BACKUP LOG [$DbName] to DISK='$DbFile.TRN'
   6: GO
   7:  
   8: DBCC SHRINKFILE (N'$LogFileAlias', 0, TRUNCATEONLY)
   9: GO

Well they aren’t true SQL statements as I have used a few variables in there, however that is enough for you to get the idea.

The first statement backs up the $DbName (powershell variable) to $DbFile.

The second statement backs up the log file.

And the third statement truncates the log file, which we just backed up.

Second step. Execute SQL using PowerShell

This is easier than it looks as PowerShell enables you to call any .NET component.

   1: function execute-Sql($server, $db, $sql )
   2: {
   3:   $Connstring = "server=$server;integrated security=TRUE;database=$db"
   4:  
   5:   $sqlConnection = new-object System.Data.SqlClient.SqlConnection
   6:   $sqlConnection.ConnectionString = $Connstring 
   7:   $sqlConnection.Open()
   8:  
   9:   $sqlCommand = new-object System.Data.SqlClient.SqlCommand
  10:   $sqlCommand.CommandTimeout = 120
  11:   $sqlCommand.Connection = $sqlConnection
  12:   $sqlCommand.CommandText= $sql
  13:   $text = $sql.Substring(0, 50)
  14:   Write-Progress -Activity "Executing SQL" -Status "Executing SQL => $text..."
  15:   Write-Host "Executing SQL => $text..."
  16:   $result = $sqlCommand.ExecuteNonQuery()
  17:   $sqlConnection.Close()
  18: }

Apart from a few text logging lines 13 through 15.  The rest is reasonably straight forward.  Create a connection to the $db on $server and execute $sql.

If you have a few databases you want to backup then calling this method could become rather tedious.  So lets wrap Step 1 and Step 2 together.

   1: Function BackupDB($Server, $DbName, $DbFile, $LogFileAlias)
   2: {
   3:   execute-sql $server $DbName "BACKUP DATABASE [$DbName] to DISK='$DbFile.BAK' WITH FORMAT, NAME='$DbName-Full Database Backup'"
   4:   execute-sql $server $DbName "BACKUP LOG [$DbName] to DISK='$DbFile.TRN'"
   5:   execute-sql $server $DbName "DBCC SHRINKFILE (N'$LogFileAlias', 0, TRUNCATEONLY)"
   6: }

 

Third step. Manage the Backup files.

Ok so now we can generate the SQL backup files and manage the database with a couple of lines.

   1: $curdate = Get-Date
   2: $formDate=$curdate.ToString("yyyyMMddhhmm")
   3: BackupDB  ".\SQLExpress" "Northwind" "c:\SQLBackup\Northwind-$formdate" "Northwind_Log"

These three lines will create a backup file and a Transaction log backup file of the form Northwind-yyyyMMddhhmm in the c:\SQLBackup folder.

If this is scheduled using a task scheduler we are going to have a lot of backup files build over time so we need one more helper function to manage these files.

   1: Function DelOldFile($Dir, $Pattern, $Days)
   2: {
   3:  if (Test-Path $Dir)
   4:  {
   5:   $Now = Get-Date
   6:   # Notice the minus sign before $days
   7:   $LastWrite = $Now.AddDays(-$days)
   8:   $Files = get-childitem "$Dir" -include "$Pattern" -recurse | Where {$_.LastWriteTime -le "$LastWrite"} 
   9:  
  10:   foreach ($File in $Files)
  11:   #You can add -whatif to see the consequence – Remove-item $File -Whatif
  12:   {write-host "Deleting File $File" -foregroundcolor "Red"; Remove-Item $File |out-null}
  13:  }
  14:  Else
  15:  {Write-Host "The Folder $Dir Does Not Exist!"}
  16: }

Bingo… this function deletes any files under $Dir that match $Pattern and are older than $Days.

So after doing the backup we can call this function to remove any old backups that we don’t want anymore.

e.g.

   1: DelOldFile "c:\SQLBackup" "Northwind*.BAK" 60
   2: DelOldFile "c:\SQLBackup" "Northwind*.TRN" 60

 

Fourth Step.  Schedule the Script.

This is easy.  Just setup a Windows Task to call powershell and execute the script. 

Ok… so to put it altogether you will need to paste the above script functions into a powershell script file, and do something so that the backup files end up on some other media than on the same disk spindle.  That defeats the purpose of a backup.  But that I’ll leave up to you to work out.

Categories: Programming

Last week…

9 February 2009 Leave a comment

Last week I worked a 53 hour week.  Why, I hear you ask, would you do that when you are only paid for 37.5 hours?  The answer is simple.  I enjoyed what I was doing.

Last week I got dig into WiX (http://wix.sourceforge.net/) and use it to create an installation package packed with features.  Here are some of the points that I discovered.

1. You can still use the WiX 3 execute custom action to run a .NET application at the end of the installation despite not being able to actually execute the .NET code as a custom action. (Which actually is just really fiddly to do, not impossible.) see http://wix.sourceforge.net/manual-wix3/qtexec.htm for further information.

2. Tallow has been replaced by Heat in version 3 of Wix.  However, Heat doesn’t have the synchronisation features Mallow has.  Fortunately Neil Sleightholm’s has modified Mallow for WiX v3

3. The Votive extensions for Visual studio, somehow, ended up consuming 48% of my CPU power permanently when in use, so I edited the files manually once I got the basics done.

And finally after hours, literally, of messing around with the build process I got a fully automated build and deploy of the project working.

Categories: Programming