Archives

Archives / 2013 / October
  • Visual Studio cleared / deleted my ascx.g.cs file when adding a Register declaration in my web part

    Tags: SharePoint 2013, Visual Studio 2012, WebParts

    Having landed on this page, you’ve most likely experienced the joy of VS clearing the contents of your ascx.g.cs file when adding a Register declaration, in the hope you can simply drop in your super whizzy snap bang custom control.

    Well, firstly rest assured you have not killed anything.  VS will rebuild the file for you.

    In the background VS communicates with SharePoint when you save the ascx file to build that cs file and if there are any issues, it just bums out and builds nothing.  Awesome!

    You will probably find that you need to deploy your assembly containing the namespace before you try and use it in your web part.  That way when VS talks to SharePoint, it knows about your namespace.

    More info, some comments from MS and lots of user experience/anger can be found here.

    http://connect.microsoft.com/VisualStudio/feedback/details/776340/visual-web-part-in-vs2012-code-in-ascx-g-cs-is-erased#tabs

    more...

  • Build JS file for .net Constants class

    Tags: PowerShell, javascript, SharePoint, SharePoint 2013

    It’s pretty common practice for me to have a Constants class in all my projects, especially so in SharePoint projects where you are likely to have Field name, Content Type ID’s and probably some GUID’s that you need.

    As I find myself more and more developing javascript solutions, I want access to those constants on the client side.  So taking inspiration from SharePoint (which generates a Strings object in javascript – see /_layouts/15/<lcid>/string.js, this file is auto generated by stsadm.exe.  I decided to cobble together a little script to build my js file.

    Say you have a .net constants class similar to this (I also use nested classes in my constants class).

    // Note: This file is autogenerated in JS for use on the client side.
    //       Do NOT put any sensitive string values in it.
    public static class MyStrings
    {
        public static class NestedOne
        {
            public static class NestedTwo
            {
                public const string Foo = "FooString";
                public const string Bar = "BarString";
    
                public static class NestedThree
                {
                    public const string Address1 = "AddressLine1";
                }
            }
    
            public static class NestedTwoTwo
            {
                public const string Location = "Location";
            }
    
            public const string AnotherOne = "SomeValue123";
        }
    }

     

    And use this PowerShell scripts (it’s a litle muddly I know, but it does work nicely!)
    Note: You could remove the string builder, its just there to help with debugging.

    The script is going to recursively loop through all your nested classes and build the required javascript file.

    clear
    $dllPath = 'C:\Constants.dll' #Path to dll containing Constants class
    $constantsClassName = "MyStrings" #Name of the .net constants class
    $jsClassName = "MyJsStrings"; #Name of the object in Javascript
    $outputJsFilePath = "C:\dump\MyJsStrings.js" #Place to save output js file
    
    # StringBuilder is just for debugging, you can change to simply write to stream
    $sb = New-Object -TypeName "System.Text.StringBuilder"
    $stream = [System.IO.StreamWriter] $outputJsFilePath
    
    function Append([string] $val) {
    	[Void]$sb.AppendLine($val)
    }
    
    Append "/* Copyright message ... "
    Append " * This file has been auto generated, do NOT edit"
    Append " */"
    
    function WriteFields ([System.Reflection.MemberInfo]$member, $parent) {
    	foreach($f in $member.GetFields() | where { $_.FieldType.Name -eq "String"}) {
    		$t = $jsClassName+"."
    		
    		if(-not [System.String]::IsNullOrWhiteSpace($parent)) {
    			$t += $parent+"."
    		} 
    		$t += $member.Name+"."+$f.Name+"='"+$f[0].GetValue($null)+"';"
    		Append $t
    	}
    	Append ""
    }
    
    function Recurse ([System.Reflection.MemberInfo]$member, $parent) {
    	WriteFields $member $parent
    	
    	foreach($mem in $member.GetMembers() | where { $_.IsClass -eq $true }) {
    		if(-not [System.String]::IsNullOrWhiteSpace($parent)) {
    			Append ($jsClassName+"."+$parent+"."+$member.Name+"."+$mem.Name+"=function(){};")
    			Recurse $mem ($parent+"."+$member.Name)
    		} else {		
    			Append ($jsClassName+"."+$member.Name+"."+$mem.Name+"=function(){};")
    			Recurse $mem $member.Name
    		}
    	}
    }
    
    # Load the dll
    # Doing it this way doesn't lock the file, could also be done with a new AppDomain
    
    $fileBytes = [IO.File]::ReadAllBytes($dllPath)
    
    $assembly = [Reflection.Assembly]::Load($fileBytes)
    
    # Get Constants class, could easily be modified if you have more that one class
    $classes = $assembly.GetTypes() | where { $_.Name -eq $constantsClassName }
    
    Append ("var "+$jsClassName+"=new Object();")
    
    foreach($c in $classes) {
    	foreach($m in $c.GetMembers() | where { $_.IsClass -eq $true }) {
    		$t = $jsClassName+"."+$m.Name+"=function(){};"
    		Append $t $m.Name
    		Recurse $m
    	}
    }
    
    Write $sb.ToString()
    $stream.Write($sb.ToString())
    $stream.Close();
    $stream.Dispose();

     

    The output is something like this…

    /* Copyright message ... 
     * This file has been auto generated, do NOT edit
     */
    var MyJsStrings=new Object();
    MyJsStrings.NestedOne=function(){};
    MyJsStrings.NestedOne.AnotherOne='SomeValue123';
    
    MyJsStrings.NestedOne.NestedTwo=function(){};
    MyJsStrings.NestedOne.NestedTwo.Foo='FooString';
    MyJsStrings.NestedOne.NestedTwo.Bar='BarString';
    
    MyJsStrings.NestedOne.NestedTwo.NestedThree=function(){};
    MyJsStrings.NestedOne.NestedTwo.NestedThree.Address1='AddressLine1';
    
    MyJsStrings.NestedOne.NestedTwoTwo=function(){};
    MyJsStrings.NestedOne.NestedTwoTwo.Location='Location';
    

     

    Add a link to that file in VS or add it to your _reference.js file and you’ll get nice intellisense!!

    Hope you find this as useful as I did!

    more...

  • Merge multiple dll ‘s into one WPF application

    Tags: .NET, WPF

    It’s pretty standard scenario to have your application reference assemblies that are not part of the .net framework.  In those instances the default behaviour is for VS to sit those dll’s along side your built .exe file.

    Of course the application won’t run without them, but it can be a pain (or at least unwanted) to have to deploy these dll’s with the application.  Especially if you want to share/move the .exe file around the place.

    ILMerge to the rescue, this is a groovy little tool from Microsoft that will “Merge” your dll’s into a single dll/exe.  However, this does not work with WPF applications and was never designed too.

    After a little digging around I found this solution, it does require a little code, but nothing heavy.  I’d actually rather have this piece of code than flakey post build commands anyway.

    Essentially you add your dll to the application in VS, set it as an Embedded Resource and put the code chunk below into the Application OnStartup event.

    protected override void OnStartup(StartupEventArgs e)
    {
    	base.OnStartup(e);
    	AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => {
    
    		string resourceName = "<Your namespace>.<folder name dll is in>." + new AssemblyName(args.Name).Name + ".dll";
    
    		try {
    			using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName)) {
            	        	Byte[] assemblyData = new Byte[stream.Length];
    		                stream.Read(assemblyData, 0, assemblyData.Length);
            	        	return Assembly.Load(assemblyData);	
    			}
    	        } catch (Exception ex) {
    			throw new System.IO.FileLoadException("Cannot find dll embedded resource - " + resourceName, ex);
    	        }
    	};
    }

    Don't forget to change the reference to the assembly to "Copy Local = False", we don’t need that to copy anymore!

    Further:
    Costura is a tool/add in that will basically do the above, without writing the code.  I’m happy with the code!

    more...